useUpdateAllTrainCarsCoordinates.tsx
unknown
plain_text
2 years ago
6.1 kB
11
Indexable
import {useEffect, useMemo, useRef} from 'react';
import {useSelector, useDispatch} from 'react-redux';
import GetLocation from 'react-native-get-location';
import {getConsistTrain} from '@Redux/train/selectors';
import {
getRunningStatus,
getUseSimulatedTestData,
getUseTestData,
} from '@Redux/common/selectors';
import {getTrackGroupData} from '@Redux/track/selectors';
import {
setAllTrainCarsInfo,
setAngle,
setPosition,
setLocationData,
getLiveDemoData,
setTrainLineData,
} from '@Redux/info/actions';
import {setOutOfTrack} from '@Redux/common/actions';
import {getLocationData} from '@Redux/info/selectors';
import {getAngle} from '@Utils/getCorridorSegmentDetails';
import {getTrainCarsDetails, getLineEndCoord} from '@Utils/computeTrainData';
import {getDistanceToTrack} from '@Utils/geometryHelper';
import {getCleanedGpsPoint} from '@Utils/cleanGpsData';
import {generateSimulatedGpsPoints} from '@Utils/simulationModeHelper';
import {
DEFAULT_LOCOMOTIVE_LENGTH_IN_MILES,
DEFAULT_RAIL_CAR_LENGTH_IN_MILES,
FT_TO_MILE,
SNAP_TO_TRACK_DISTANCE,
} from '@Constants';
const useUpdateAllTrainCarsCoordinates = (
trackCoords: any[][],
track: any[],
currentTripKey: string,
) => {
const dispatch = useDispatch();
const runningStatus = useSelector(getRunningStatus);
const useTestData = useSelector(getUseTestData);
const useSimulatedTestData = useSelector(getUseSimulatedTestData);
const trackGroupData = useSelector(state => getTrackGroupData(state));
const speedLimitList =
trackGroupData[currentTripKey]?.data?.trackSpeedLimit || [];
const absoluteStartTrackDistanceMiles =
(track?.length > 0 && track[0]?.absoluteStartTrackDistanceMiles) || 0;
const simulatedLocationData = useTestData
? useMemo(
() =>
generateSimulatedGpsPoints(
track,
trackCoords,
speedLimitList,
absoluteStartTrackDistanceMiles,
),
[track, trackCoords],
)
: null;
const locationData = useSelector(state => getLocationData(state));
// Get consist data and create train cars info
const consistTrain = useSelector(getConsistTrain);
const trainLengthInFt = consistTrain?.totalLengthFt || 0;
const trainLengthInMiles = trainLengthInFt * FT_TO_MILE;
const locomotiveCount = consistTrain?.locomotiveCount || 1;
const locomotivesLengthInMiles =
locomotiveCount * DEFAULT_LOCOMOTIVE_LENGTH_IN_MILES;
const trainCarsInfo: any = useMemo(() => {
const locomotiveList = [...Array(consistTrain?.locomotiveCount || 0)].map(
() => ({
type: 'locomotive',
carLengthInMiles: DEFAULT_LOCOMOTIVE_LENGTH_IN_MILES,
}),
);
const carList = [...Array(consistTrain?.carCount || 0)].map(() => ({
type: 'car',
carLengthInMiles: DEFAULT_RAIL_CAR_LENGTH_IN_MILES,
}));
return [...locomotiveList, ...carList];
}, [consistTrain]);
const processTrainData = (location: any) => {
const deviceCoord = [location.latitude, location.longitude];
const withinSnapToTrackDistance =
getDistanceToTrack(deviceCoord, trackCoords) <= SNAP_TO_TRACK_DISTANCE;
// Apply cleaning algorithm if applicable
if (withinSnapToTrackDistance) {
const cleanCoord = getCleanedGpsPoint(deviceCoord, trackCoords);
const angle = getAngle(cleanCoord, trackCoords);
// Then compute start and end coordinates of train line
const trainLineData = {
locoStartCoord: cleanCoord,
locoEndCoord: getLineEndCoord(
cleanCoord,
locomotivesLengthInMiles,
trackCoords,
),
trainEndCoord: getLineEndCoord(
cleanCoord,
trainLengthInMiles,
trackCoords,
),
};
// Then compute info (coordinates, angle) of all train cars
const updatedTrainCarsInfo = [
{
...trainCarsInfo[0],
coord: cleanCoord,
angle,
},
...trainCarsInfo.slice(1),
];
const newTrainCarsInfo = getTrainCarsDetails(
updatedTrainCarsInfo,
trackCoords,
);
dispatch(setTrainLineData(trainLineData));
dispatch(setAllTrainCarsInfo(newTrainCarsInfo));
dispatch(setPosition(cleanCoord));
dispatch(setAngle(angle));
dispatch(setOutOfTrack(false));
} else {
dispatch(setPosition(deviceCoord));
dispatch(setAngle(null));
dispatch(setOutOfTrack(true));
}
};
// Get location data from device
const getDeviceLocationData = () => {
try {
GetLocation.getCurrentPosition({
enableHighAccuracy: true,
timeout: 15000,
})
.then(location => {
dispatch(setLocationData(location));
processTrainData(location);
})
.catch(error => {
console.log(error?.message || '');
});
} catch (error: any) {
console.log(error?.message || '');
}
};
const locationIndex = useRef(0);
const getSimulatedLocationData = () => {
if (!simulatedLocationData) {
return;
}
if (!runningStatus) {
return;
}
if (locationIndex.current > simulatedLocationData.length - 1) {
return;
}
const location = simulatedLocationData[locationIndex.current];
dispatch(setLocationData(location));
processTrainData(location);
locationIndex.current++;
};
const getLiveSimulatedLocationData = () => {
dispatch(getLiveDemoData());
};
useEffect(() => {
if (locationData && useSimulatedTestData) {
processTrainData(locationData);
}
}, [locationData]);
useEffect(() => {
locationIndex.current = 0;
let interval = setInterval(() => {
if (useTestData) {
getSimulatedLocationData();
} else if (useSimulatedTestData) {
getLiveSimulatedLocationData();
} else {
getDeviceLocationData();
}
}, 1000);
return () => {
clearInterval(interval);
};
}, [currentTripKey, runningStatus]);
};
export default useUpdateAllTrainCarsCoordinates;
Editor is loading...