1

We are attempting to create a routing (TSP) algorithm that loops through a data structure that holds our vehicles and our trip information.

It all starts with an ASYNC function called acquireData that makes a $.getJSON call to our own API which returns a large object structure of all our vans and trips and all (too much) the information. This async function loops through the API object return and builds a brand new object with a LOT less data...

It returns the new object as a result.

At the bottom we call the async function and then we want to do all the TSP solving in the .then().

In the .then() we log "data" (which is the returned object from the async function acquireData()) and everything looks good. The image aboce is console.log(data.trucks). You can see all the avilableAt properties have a different date/time except for the ones who do not have a trip. This is the way its supposed to be. All is good up to this point, the data is exactly as we want it.

console.log(data)

Now here is where we start to run into the issue...

When we attempt to loop through this data.trucks, the availableAt properties go haywire. $.each(data.trucks, function(d, j){ console.log(d, j.availableAt)})

Once we loop through this and display the availableAt properties, they all get the same date/time. Compare the two picture's and look at "Med 2" you'll see the difference.


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
  <title>Document</title>
</head>
<body>

  <script>

    function createDateObject(dateString, militaryTime) {
      if (typeof dateString === "boolean" || typeof militaryTime === "boolean" || militaryTime == ""){
        
        return "No Date"
      } else {
        const year = parseInt(dateString.slice(0, 4));
        const month = parseInt(dateString.slice(5, 7)) - 1;
        const day = parseInt(dateString.slice(8, 10));
        const hours = parseInt(militaryTime);
        const date = new Date(year, month, day, hours);
        return date;
      }
    }

    function formatCityState(city, state) {
      const formattedCity = city.replace(/ /g, '+');
      const formattedState = state.toUpperCase();
      return `${formattedCity},${formattedState}`;
    }

    function addSeconds(date, seconds) {
      var newDate = new Date(date.getTime() + seconds * 1000);
      return newDate;
    }

    function isBefore(date1, date2) {
      return date1.getTime() < date2.getTime();
    }

    function addHalfHourEvery4Hours(seconds) {
      var hours = seconds / 3600; // convert to hours
      var timeSlots = Math.floor(hours / 4); // calculate number of 4-hour time slots
      var extraHours = timeSlots * 0.5; // calculate extra half-hours
      var newHours = hours + extraHours; // add extra half-hours to original hours
      var newSeconds = newHours * 3600; // convert back to seconds
      return newSeconds;
    }

    const callGoogle = async(origin, destination) => {
      const params = encodeURIComponent('&origins=' + origin + '&destinations=' + destination);
      const grabData = await $.getJSON('no-cors.php?url=https://maps.googleapis.com/maps/api/distancematrix/json?' + params + '&key=xxxxxxx')
      return grabData;
      }

    async function acquireData() {
    const data = await new Promise((resolve, reject) => {
      $.getJSON('https://xxxxxxxxxx/xxxxx.php', function(data) {
      const newData = {
        // employees: {},
        trucks: {},
        trips: [],
        trips_unscheduled: []
      };
      $.each(data.trucks, function(j, k) {
        const truckObj = {
          trips: [],
          standing_location: k.name_value_list.location_c.value
        };
        if (j.includes('Med') || j == "") {
          if (k.trips) {
            for (let i = 0; i < k.trips.length; i++) {
              const tripDate = new Date(k.trips[i].name_value_list.transport_date_2_c.value);
              const now = new Date();
              const timeDiff = tripDate - now;
              const diffInHours = timeDiff / (1000 * 3600);
              const tripObj = {
                trip_id: k.trips[i].name_value_list.trip_id_c.value,
                dropoff_location: formatCityState(k.trips[i].name_value_list.arrival_city_c.value, k.trips[i].name_value_list.arrival_state_c.value),
                pickup_location: formatCityState(k.trips[i].name_value_list.departure_city_c.value, k.trips[i].name_value_list.deprature_state_c.value),
                pickup_time: createDateObject(k.trips[i].name_value_list.transport_date_2_c.value, k.trips[i].name_value_list.pick_up_time_c.value, k.trips[i].name_value_list.trip_id_c.value)
              };

              if (diffInHours > 48 && tripObj.pickup_time != "No Date") {
                newData.trips.push(tripObj);
              } else if (diffInHours < -45000 || tripObj.pickup_time == "No Date") {
                newData.trips_unscheduled.push(tripObj)
              } else {
                truckObj.trips.push(tripObj);
              }
            }
            //Generate availableAt for trucks with trips.
            if (truckObj.trips.length > 0) {
              var Corndogs = callGoogle(truckObj.trips[truckObj.trips.length - 1].pickup_location, truckObj.trips[truckObj.trips.length - 1].dropoff_location)
              .then((data) => {
                truckObj.availableAt =  addSeconds(truckObj.trips[truckObj.trips.length - 1].pickup_time ,addHalfHourEvery4Hours(data.rows[0].elements[0].duration.value))
                newData.trucks[j] = truckObj;
              })
            } 
          }
          //Generate availableAt for trucks with no trips. 
          let t = new Date()
          let tomorrow = new Date(t.setHours(t.getHours() + 24))
          truckObj.availableAt = tomorrow
          newData.trucks[j] = truckObj;
        }
      });
      resolve(newData);
    });
  });
  return data;
}

//now that we have our data built out the way we want it, we can loop through it and find the best truck for each trip.



//We will start by looping through each trip. 
  //Loop through each truck
    //if truck availableAt is before pickup time that means this truck is a possibility for current trip
      //calculate if the truck can make it to the trip pickup location in time
        //if it can lets save the travel time and distance in a variable as well as the good truck
          //loop through trips again and if there is a trip that is closer and has less sitting time lets replace 
          //continue looping through all the trucks ; everytime we find a truck that can make the trip but is less travel time and distance , save these details to the variable.
           
          
//Loop through each truck
  //Loop through each trip
    //if truck availableAt is before the tripPickUpTime then lets dive further
      //calculate travel time and distance from trucks drop off and avaialbleAt
        //if truck can make it in time
          //lets save that distance and time spent sitting into a variable and save that truck 
            //continue to compare it to other trucks nd if we find a lower distance/time
              //once we have looked through all the trucks  



acquireData().then((data) => {

  console.log(data)

  $.each(data.trucks, function(d, j){
    console.log(d, j.availableAt)
  })
  // console.log(data.trucks)

}).catch((error) => {
  console.error(error);
});



  </script>
  
</body>
</html>

3
  • instead of if (k.trips) try if (k.trips.length > 0). Also be aware that the part you set the date is in that if, so it would set it for all. I'd suggest to put those 4 lines into the else part of that if-statement. Commented Mar 17, 2023 at 13:06
  • @kathara Unfortunately this does not solve the problem. I don't know if the bug is in the acuireData function to be honest. That functions builds out the data just the way we want it. Commented Mar 17, 2023 at 13:13
  • 2
    dump logs as code inside the question instead linking to external images... Commented Mar 17, 2023 at 14:26

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.