organize code for optimal path, ensure miles are used

This commit is contained in:
Michael Fatemi 2021-07-14 13:08:25 -04:00
parent fa5a9df5da
commit 052236e20a
5 changed files with 86 additions and 62 deletions

View File

@ -1,10 +1,9 @@
import CancelIcon from '@material-ui/icons/Cancel'; import CancelIcon from '@material-ui/icons/Cancel';
import CheckIcon from '@material-ui/icons/Check'; import CheckIcon from '@material-ui/icons/Check';
import EmojiPeopleIcon from '@material-ui/icons/EmojiPeople'; import EmojiPeopleIcon from '@material-ui/icons/EmojiPeople';
import { useEffect } from 'react'; import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { useCallback, useContext, useMemo, useState } from 'react';
import { lightgrey } from '../../lib/colors'; import { lightgrey } from '../../lib/colors';
import furthestPoint from '../../lib/furthestpoint'; import { Location } from '../../lib/estimateoptimalpath';
import { import {
useCancelCarpoolRequest, useCancelCarpoolRequest,
useInvitationState, useInvitationState,
@ -15,9 +14,33 @@ import { useMe } from '../hooks';
import { IEvent } from '../types'; import { IEvent } from '../types';
import UIButton from '../UI/UIButton'; import UIButton from '../UI/UIButton';
import UILink from '../UI/UILink'; import UILink from '../UI/UILink';
import EventContext from './EventContext'; import useOptimalPath from '../useOptimalPath';
import estimateOptimalPath, { Location } from '../../lib/estimateoptimalpath';
import usePlace from '../usePlace'; 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({ function CarpoolRow({
carpool, carpool,
@ -32,8 +55,6 @@ function CarpoolRow({
const cancelCarpoolRequest = useCancelCarpoolRequest(); const cancelCarpoolRequest = useCancelCarpoolRequest();
const sendCarpoolRequest = useSendCarpoolRequest(); const sendCarpoolRequest = useSendCarpoolRequest();
const { signups } = useContext(EventContext);
const sendButton = useCallback(() => { const sendButton = useCallback(() => {
sendCarpoolRequest(carpool.id); sendCarpoolRequest(carpool.id);
}, [sendCarpoolRequest, carpool.id]); }, [sendCarpoolRequest, carpool.id]);
@ -49,53 +70,25 @@ function CarpoolRow({
const myLocation = usePlace(myPlaceId); const myLocation = usePlace(myPlaceId);
const extraDistance = useMemo(() => { const memberLocations = useMemberLocations(carpool.members);
if (!myLocation) {
console.log('!myLocation');
return null;
}
// Calculates the minimum distance if I'm in the carpool const pathInCarpool = useOptimalPath(memberLocations, {
// and subtracts the distance if I'm not in the carpool latitude,
longitude,
});
const memberLocations = carpool.members const pathNotInCarpool = useOptimalPath(
.map((member) => { myLocation ? [...memberLocations, myLocation] : [],
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, {
latitude, latitude,
longitude, longitude,
}); }
);
const passengerLocations = memberLocations.filter( const extraDistance =
(location) => location !== driverLocation myLocation && pathInCarpool && pathNotInCarpool
); ? pathInCarpool.distance - pathNotInCarpool.distance
: null;
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);
return ( return (
<div <div
@ -113,20 +106,16 @@ function CarpoolRow({
> >
{/* <div> */} {/* <div> */}
<span <span
style={{ fontWeight: 600, cursor: 'pointer' }} style={{ cursor: 'pointer' }}
onClick={() => { onClick={() => {
window.location.href = '/carpools/' + carpool.id; window.location.href = '/carpools/' + carpool.id;
}} }}
> >
{carpool.name} {extraDistance !== null && '+ ' + extraDistance} <b>{carpool.name}</b>
{extraDistance !== null && ' +' + extraDistance.toFixed(1) + ' miles'}
</span> </span>
<br /> <br />
<br /> <br />
{/* <div style={{ display: 'flex', alignItems: 'center' }}>
<CallMergeIcon style={{ marginRight: '1rem' }} />{' '}
<b>{carpool.extraDistance} miles</b>
</div> */}
{/* </div> */}
{!inCarpoolAlready && ( {!inCarpoolAlready && (
<> <>
{inviteState === 'none' ? ( {inviteState === 'none' ? (

View File

@ -28,7 +28,7 @@ function EventSignup({
hasCarpool, hasCarpool,
} = useContext(EventContext); } = useContext(EventContext);
let extraDistance = useMemo(() => { const extraDistance = useMemo(() => {
if (myPlaceDetails != null && !(latitude === null || longitude === null)) { if (myPlaceDetails != null && !(latitude === null || longitude === null)) {
const myLatitude = myPlaceDetails.latitude; const myLatitude = myPlaceDetails.latitude;
const myLongitude = myPlaceDetails.longitude; const myLongitude = myPlaceDetails.longitude;
@ -90,8 +90,10 @@ function EventSignup({
}} }}
key={user.id} key={user.id}
> >
<b>{user.name}</b> <span>
{extraDistance ? `: +${extraDistance.toFixed(1)} miles` : ''} <b>{user.name}</b>
{extraDistance ? ` +${extraDistance.toFixed(1)} miles` : ''}
</span>
{!hasCarpool && {!hasCarpool &&
(isTentativelyInvited ? ( (isTentativelyInvited ? (

View File

@ -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]);
}

View File

@ -6,7 +6,7 @@ export default function furthestPoint(
destination: Location destination: Location
) { ) {
let maxDistance = 0; let maxDistance = 0;
let maxLocation = { latitude: 0, longitude: 0 }; let maxLocation = null;
for (let i = 0; i < locations.length; i++) { for (let i = 0; i < locations.length; i++) {
let distance = getDistance(locations[i], destination); let distance = getDistance(locations[i], destination);

View File

@ -1,5 +1,5 @@
import { Location } from './estimateoptimalpath'; import { Location } from './estimateoptimalpath';
import latlongdist from './latlongdist'; import latlongdist, { R_miles } from './latlongdist';
export default function getDistance(...locations: Location[]): number { export default function getDistance(...locations: Location[]): number {
let distance = 0; let distance = 0;
@ -10,7 +10,8 @@ export default function getDistance(...locations: Location[]): number {
from.latitude, from.latitude,
from.longitude, from.longitude,
to.latitude, to.latitude,
to.longitude to.longitude,
R_miles
); );
} }
return distance; return distance;