gpsData.ts

mail@pastecode.io avatar
unknown
typescript
7 months ago
11 kB
2
Indexable
Never
// Utils
import {getBearingAngle} from '@Utils/geometryHelper';
import {
  getSegmentIdFromCoord,
  getCorridorCoordsOnly,
} from '@Utils/getCorridorSegmentDetails';
import {appendToJsonFile, createJsonFile} from '@Utils/fileHelper';

// Types
import {LatLng} from '@Types';
import {S3PathKey} from '@Types';

/**
 * It returns a random string of the form "XXXX-XXXX-XXXX-XXXX" where each X is a random hexadecimal
 * digit
 * @returns A function that returns a string of 4 random numbers and letters.
 */
export const idGenerator = () => {
  const S4 = function () {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  };
  return S4() + '-' + S4() + '-' + S4() + '-' + S4();
};

/**
 * Return a random integer between min and max, inclusive.
 * @param {number} min - The minimum number that can be returned.
 * @param {number} max - The maximum number.
 * @returns A random integer between min and max
 */
export const getRandomInt = (min: number, max: number) => {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
};

/**
 * It generates a random GPS data object with a random altitude, speed, course, and accuracy
 * @param {number} lat - latitude
 * @param {number} lng - longitude
 * @param {number} alt - altitude
 * @returns An object with the following properties:
 * sequenceId: a random number
 * location: an object with the following properties:
 *   coordinate: an object with the following properties:
 *    lat: a lat provided
 *    lng: a lng provided
 *    horizontal_accuracy: a random number between 1 and 5
 * alt: an object with the following properties:
 *    alt: a random number between -180 and 180
 *    ellipsoidal: a random number between -180 and 180
 *    vertical_accuracy: a random number between 1 and 5
 * courseVector: an object with the following properties:
 *    speed: a random number between 1 and 60
 *    speedAccuracy: a random number between 1 and 5
 *    course: a random number between 0 and 360
 *    courseAccuracy: a random number between 4 and 6
 * timeStamp: current timeStamp in the format "mm/dd/yyyy, hh:mm:ss"
 */

export const generateGpsData = (location: any) => {
  const today = new Date().toISOString();
  const timeStamp = `${today.slice(5, 7)}/${today.slice(8, 10)}/${today.slice(
    0,
    4,
  )}, ${today.slice(11, 19)}`;
  return {
    sequenceId: idGenerator(),
    location: {
      coordinate: {
        lat: Number(JSON.stringify(location.latitude)),
        lng: Number(JSON.stringify(location.longitude)),
        horizontal_accuracy: Number(JSON.stringify(location.accuracy)),
      },
      alt: {
        alt: Number(JSON.stringify(location.altitude)),
        ellipsoidal: Number(JSON.stringify(location.altitude)),
        vertical_accuracy: Number(JSON.stringify(location.verticalAccuracy)),
      },
    },
    courseVector: {
      speed: Number(JSON.stringify(location.speed)),
      speedAccuracy: Number(JSON.stringify(location.accuracy)),
      course: Number(JSON.stringify(location.course)),
      courseAccuracy: Number(JSON.stringify(location.accuracy)),
    },
    timeStamp: timeStamp,
  };
};

/**
 * It takes the railroad_id and returns the name of the file that will be used to store the GPS data
 * @param {string} railroad_id - The railroad's ID.
 * @returns A string with the name of the file that will be used to store the GPS data
 */
export const generateGPSFileName = (
  railroad_id: string,
  simple_train_consist_id: string,
) => {
  const today = new Date().toISOString();
  const year = today.slice(0, 4);
  const month = today.slice(5, 7);
  const day = today.slice(8, 10);
  const epochTimeStamp = Date.now();
  return `${railroad_id}:${year}:${month}:${day}:${epochTimeStamp}:${simple_train_consist_id}`;
};

/**
 * It creates a new JSON file with the filename provided, and the JSON schema provided
 * @param {string} railroad_id - The ID of the railroad you're on.
 * @param {string} trip_id - This is the trip_id that you want to use.
 * @param {string} user_id - The user_id of the user who is creating the file.
 * @param {string} filename - the name of the file to be created
 * @param {any} location - the location object that will be used to generate the first GPS log
 */
export const createNewGPSFile = async (
  railroad_id: string,
  trip_id: string,
  user_id: string,
  filename: string,
  location: any,
  simple_train_consist_id: string,
  loco_id: string,
) => {
  const jsonSchema = {
    railroad_id: railroad_id,
    trip_id: trip_id,
    user_id: user_id,
    simple_train_consist_id: simple_train_consist_id,
    loco_id: loco_id,
    created_at_utc: new Date().toISOString(),
    data: [generateGPSJsonLog(location)],
  };
  const stringify = JSON.stringify(jsonSchema);
  await createJsonFile(
    S3PathKey.GPS,
    filename,
    stringify.slice(0, stringify.length - 2),
  );
};

/**
 * It takes a filename and a location object, generates a GPS log object, stringifies it, and appends
 * it to the file
 * @param {string} filename - the name of the file to append to
 * @param {any} location - the location object that will be used to generate the GPS log
 */
export const appendToGPSFile = async (filename: string, location: any) => {
  const gpsLog = generateGPSJsonLog(location);
  const stringify = JSON.stringify(gpsLog);
  await appendToJsonFile(S3PathKey.GPS, filename, `,${stringify}`);
};

/**
 * It takes a location object and returns a GPS log object
 * @param {any} location - the location object that will be used to generate the GPS log
 * @returns A JSON object
 */
export const generateGPSJsonLog = (location: any) => {
  const gpsLog = {
    timestamp_utc: new Date().toISOString(),
    position: {
      coordinate: {
        lat: location?.latitude,
        lng: location?.longitude,
        gps_error_radius_m: location?.accuracy,
      },
      altitude: {
        alt_m: location?.altitude,
        alt_error_m: location?.verticalAccuracy,
      },
    },
    velocity: {
      speed_mps: location?.speed,
      speed_error_mps: 0,
      course: location?.course,
      course_error: 0,
    },
  };
  return gpsLog;
};

/**
 * It takes a filename and a location object, generates a GPS log object, stringifies it, and appends
 * it to the file
 * @param {string} filename - the name of the file to append to
 * @param {any} location - the location object that will be used to generate the GPS log
 */
export const appendToGPSFileInBackground = async (
  filename: string,
  location: any,
) => {
  const gpsLog = generateGPSJsonLogInBackground(location);
  const stringify = JSON.stringify(gpsLog);
  await appendToJsonFile(S3PathKey.GPS, filename, `,${stringify}`);
};

/**
 * It takes a location object and returns a GPS log object
 * @param {any} location - the location object that will be used to generate the GPS log
 * @returns A JSON object
 */
export const generateGPSJsonLogInBackground = (location: any) => {
  const gpsLog = {
    timestamp_utc: new Date().toISOString(),
    position: {
      coordinate: {
        lat: location?.latitude,
        lng: location?.longitude,
        gps_error_radius_m: location?.accuracy,
      },
      altitude: {
        alt_m: location?.altitude,
        alt_error_m: location?.altitudeAccuracy,
      },
    },
    velocity: {
      speed_mps: location?.speed,
      speed_error_mps: 0,
      course: location?.heading,
      course_error: 0,
    },
  };
  return gpsLog;
};

/**
 * It takes in an event type, username, companyId, and eventData, and returns an object with the event
 * type, username, companyId, a timestamp, and the eventData
 * @param {string} eventType - The type of event you want to track.
 * @param {string} username - The username of the user who triggered the event.
 * @param {number} companyId - The company ID of the company that the user is currently logged into.
 * @param {string} eventData - This is the data that you want to send to the Real Time Metrics API.
 * @returns An object with the following properties:
 * eventType: string,
 * username: string,
 * companyId: number,
 * timeStamp: string,
 * eventData: string
 */
export const generateRealTimeMetricEventData = (
  eventType: string,
  username: string,
  companyId: any,
  eventData: string,
) => {
  const today = new Date().toISOString();
  const timeStamp = `${today.slice(5, 7)}/${today.slice(8, 10)}/${today.slice(
    0,
    4,
  )}, ${today.slice(11, 19)}`;
  return {
    eventType: eventType,
    username: username,
    companyId: companyId,
    timeStamp: timeStamp,
    eventData: eventData,
  };
};

/**
 * It takes in the current location of the train, the previous location of the train, and all the
 * coordinates of the corridors, and returns the current data of the train
 * @param {LatLng} location - LatLng - the current location of the train
 * @param {LatLng} prevLocation - The previous location of the train.
 * @param {any} allCorridorsData - This is the array of coordinates that make up the train tracks.
 * @returns An object with the following properties:
 * corridorName: the corridor name
 * locomotiveCoord: LatLng - the current location of the train
 * locomotiveAngle: the current locomotive Angle
 * segmentId: segment Id from coord
 */
export const calculateTrainCurrentData = (
  location: LatLng,
  prevLocation: LatLng,
  allCorridorsData: any,
) => {
  const segmentId = getSegmentIdFromCoord(
    location,
    getCorridorCoordsOnly(allCorridorsData),
  );
  let locomotiveAngle = 0;
  if (segmentId >= 0) {
    locomotiveAngle = getBearingAngle(
      [allCorridorsData[segmentId][0], allCorridorsData[segmentId][1]],
      [allCorridorsData[segmentId + 1][0], allCorridorsData[segmentId + 1][1]],
    );
  } else {
    locomotiveAngle = getBearingAngle(prevLocation, location);
  }
  const allTrainsData = [
    {
      corridorName: 'UNOS',
      locomotiveCoord: location,
      locomotiveAngle,
      segmentId,
    },
  ];
  return allTrainsData;
};

/**
 * The function converts a location schema's background properties to foreground properties.
 * @param {any} location - The `location` parameter is an object that contains information about a
 * geographical location, such as latitude, longitude, altitude, accuracy, bearing, speed, time, and
 * altitude accuracy.
 * @returns The function `convertLocationSchemaBackgroundToForeground` takes in a `location` object and
 * returns a new array with a single object that has some properties of the original `location` object.
 * The properties that are included in the new object are `accuracy`, `altitude`, `bearing` (renamed as
 * `course`), `latitude`, `longitude`, `speed`, `time`, and `altitude
 */
export const convertLocationSchemaBackgroundToForeground = (location: any) => {
  const convertedLocation = [
    {
      accuracy: location?.accuracy,
      altitude: location?.altitude,
      course: location?.bearing,
      latitude: location?.latitude,
      longitude: location?.longitude,
      speed: location?.speed,
      time: location?.time,
      verticalAccuracy: location?.altitudeAccuracy,
    },
  ];
  return convertedLocation;
};