Directions API total distance & duration with waypoints
Asked Answered
H

6

5

I am getting directions including waypoints from Directions API in my Android app. It contains multiple "leg" segments which has its own distance and duration. Is there a way to sum all distances and durations get the total values?

Example: Stripped json segment from Direction API

legs": [
{
  "distance": {
    "text": "389 km",
    "value": 389438
  },
  "duration": {
   "text": "6 hours 31 mins",
   "value": 23452
  }
},
{
  "distance": {
   "text": "0.5 km",
   "value": 487
  },
  "duration": {
   "text": "2 mins",
   "value": 102
  }
}
]

from the above response, is there a way to calculate and show the output like following:

Total distance: 389.5 km Total duration: 6 hours 33 mins

Hemmer answered 19/5, 2015 at 12:48 Comment(2)
yes, you parse response, get each item and plus them. Did you get into trouble with this?Ostmark
@Ostmark well I could do the distance, but how do I sum the duration since it can be different formats? ex minutes, hours, days and it is represented as human readable text? care to give some sample?Hemmer
O
4

As addition to my comment and answer of @Kushal here is a way how to calculate total time. I skip the way to get JSONObject, because it described already and give an example with given String[] which you get while parsing JSON. In this example I made ALL of possible scenarios with given response, so you may use it without modifying:

    String[] timeItems = {"4 days 1 hour 12 mins", "5 hours 9 mins"}; // as example for visibility
    int[] total = {0, 0, 0}; // days, hours, minutes
    for(int i = 0; i < timeItems.length; i++){
        if(timeItems[i].contains("day ")){
            total[0]++;
        }else if(timeItems[i].contains("days")){
            total[0] += Integer.valueOf(timeItems[i].substring(0, timeItems[i].indexOf(" days")));
        }
        if(timeItems[i].contains("hour ")){
            total[1]++;
        }else if(timeItems[i].contains("hours")){
            if(timeItems[i].indexOf(" hours") <= 3){
                total[1] += Integer.valueOf(timeItems[i].substring(0, timeItems[i].indexOf(" hours")));
            }else{
                if(timeItems[i].contains("days")){
                    total[1] += Integer.valueOf(timeItems[i].substring(timeItems[i].lastIndexOf("days ")) + 5, timeItems[i].indexOf(" hours"));
                }else{
                    total[1] += Integer.valueOf(timeItems[i].substring(timeItems[i].lastIndexOf("day ")) + 4, timeItems[i].indexOf(" hours"));
                }
            }
        }
        if(timeItems[i].contains("min ")){
            total[2]++;
        }else if(timeItems[i].contains("mins")){
            if(timeItems[i].indexOf(" mins") <= 3){
                total[2] += Integer.valueOf(timeItems[i].substring(0, timeItems[i].indexOf(" mins")));
            }else{
                if(timeItems[i].contains("hours")){
                    total[2] += Integer.valueOf(timeItems[i].substring(timeItems[i].indexOf("hours ") + 6, timeItems[i].indexOf(" mins")));
                }else{
                    total[2] += Integer.valueOf(timeItems[i].substring(timeItems[i].indexOf("hour ") + 5, timeItems[i].indexOf(" mins")));
                }
            }
        }
    }
    Log.d("LOG", total[0] + " days " + total[1] + " hours " + total[2] + " mins.");

This got to be a little bit more complex than I thought, maybe it is possible to simplify somehow or use similar ideas, but the main point is to show you working example. I debugged this code. It gives correct output:

05-19 23:00:38.687  14251-14251/whatever.com.myapplication D/LOG﹕ 4 days 6 hours 21 mins.

I hope this is helpful. Let me know if it either fits you or not.

Ostmark answered 19/5, 2015 at 16:3 Comment(4)
This is what I was looking for. Thank you very much. I will definitely try this and let you know how it goes. Cheers!Hemmer
Okay, will wait, happy coding :)Ostmark
There was a problem in the code and I was able to fix it. Say if the journey takes exactly 1 hour or 1 min or 1 day, the if statement for checking single day / hour / min won't get executed because there will be no trailing spaces. For example it will be "1 min" not "1 min ". I just removed the trailing space from if-else statement and reversed the order so it checks for plurals first and then singular and it works fine.Hemmer
Why not use the value field of duration? value is the duration is seconds, so just sum up all those to get total seconds, then format them as needed. Check my answer for more info.Euphuism
E
5

This adds duration to Kushal's answer:

public void parseJson(String json) {

    JSONObject jsonObj = new JSONObject(json);
    JSONObject object = (JSONObject) new JSONTokener(json).nextValue();

    JSONObject legsJson = object.getJSONObject("legs");
    long totalDistance = 0;
    int totalSeconds = 0;
    for( int i = 0; i < legsJson.size(); i++ ) {
        // distance in meter
        totalDistance = totalDistance + Long.parseLong(jsonObj[i].getJSONArray("distance").getString("value"));
        totalSeconds = totalSeconds + Integer.parseInt(jsonObj[i].getJSONArray("duration").getString("value"));
    }

    // convert to kilometer
    double dist = dist / 1000.0 ;
    Log.d("distance", "Calculated distance:" + dist);

    int days = totalSeconds / 86400
    int hours = (totalSeconds - days * 86400) / 3600;
    int minutes = (totalSeconds - days * 86400 - hours * 3600) / 60;
    int seconds = totalSeconds - days * 86400 - hours * 3600 - minutes * 60;
    Log.d("duration", days + " days " + hours + " hours " + minutes + " mins" + seconds + " seconds");
}
Euphuism answered 6/1, 2017 at 11:10 Comment(0)
O
4

As addition to my comment and answer of @Kushal here is a way how to calculate total time. I skip the way to get JSONObject, because it described already and give an example with given String[] which you get while parsing JSON. In this example I made ALL of possible scenarios with given response, so you may use it without modifying:

    String[] timeItems = {"4 days 1 hour 12 mins", "5 hours 9 mins"}; // as example for visibility
    int[] total = {0, 0, 0}; // days, hours, minutes
    for(int i = 0; i < timeItems.length; i++){
        if(timeItems[i].contains("day ")){
            total[0]++;
        }else if(timeItems[i].contains("days")){
            total[0] += Integer.valueOf(timeItems[i].substring(0, timeItems[i].indexOf(" days")));
        }
        if(timeItems[i].contains("hour ")){
            total[1]++;
        }else if(timeItems[i].contains("hours")){
            if(timeItems[i].indexOf(" hours") <= 3){
                total[1] += Integer.valueOf(timeItems[i].substring(0, timeItems[i].indexOf(" hours")));
            }else{
                if(timeItems[i].contains("days")){
                    total[1] += Integer.valueOf(timeItems[i].substring(timeItems[i].lastIndexOf("days ")) + 5, timeItems[i].indexOf(" hours"));
                }else{
                    total[1] += Integer.valueOf(timeItems[i].substring(timeItems[i].lastIndexOf("day ")) + 4, timeItems[i].indexOf(" hours"));
                }
            }
        }
        if(timeItems[i].contains("min ")){
            total[2]++;
        }else if(timeItems[i].contains("mins")){
            if(timeItems[i].indexOf(" mins") <= 3){
                total[2] += Integer.valueOf(timeItems[i].substring(0, timeItems[i].indexOf(" mins")));
            }else{
                if(timeItems[i].contains("hours")){
                    total[2] += Integer.valueOf(timeItems[i].substring(timeItems[i].indexOf("hours ") + 6, timeItems[i].indexOf(" mins")));
                }else{
                    total[2] += Integer.valueOf(timeItems[i].substring(timeItems[i].indexOf("hour ") + 5, timeItems[i].indexOf(" mins")));
                }
            }
        }
    }
    Log.d("LOG", total[0] + " days " + total[1] + " hours " + total[2] + " mins.");

This got to be a little bit more complex than I thought, maybe it is possible to simplify somehow or use similar ideas, but the main point is to show you working example. I debugged this code. It gives correct output:

05-19 23:00:38.687  14251-14251/whatever.com.myapplication D/LOG﹕ 4 days 6 hours 21 mins.

I hope this is helpful. Let me know if it either fits you or not.

Ostmark answered 19/5, 2015 at 16:3 Comment(4)
This is what I was looking for. Thank you very much. I will definitely try this and let you know how it goes. Cheers!Hemmer
Okay, will wait, happy coding :)Ostmark
There was a problem in the code and I was able to fix it. Say if the journey takes exactly 1 hour or 1 min or 1 day, the if statement for checking single day / hour / min won't get executed because there will be no trailing spaces. For example it will be "1 min" not "1 min ". I just removed the trailing space from if-else statement and reversed the order so it checks for plurals first and then singular and it works fine.Hemmer
Why not use the value field of duration? value is the duration is seconds, so just sum up all those to get total seconds, then format them as needed. Check my answer for more info.Euphuism
A
2

This method will calculate distance of all legs array :

   public void parseJson(String json) {

    JSONObject jsonObj = new JSONObject(json);
    JSONObject object = (JSONObject) new JSONTokener(json).nextValue();

    JSONObject legsJson = object.getJSONObject("legs");
    long dist = 0;
    for( int i = 0; i < legsJson.size(); i++ ) {
        // dist in meter
        dist = dist + jsonObj[i].getJSONArray("distance").getString("value");
    }

    // convert to killo meter
    float frac = dist % 1000;
    dist = dist / 1000 ;
    dist = dist + frac;
    Log.w("distance","Calculated distance :"+dist);
}
Aldebaran answered 19/5, 2015 at 13:17 Comment(1)
what about duration?Dara
O
0

Distance Calculation method. Hope this ll help someone

private String distanceCalculation(String[] distanceItems) {
    //String[] totalDis = {"50 km", "4.5 km"}; // as example for visibility
    String totalDis = "";
    float distance = 0;
    String[] splitArray;
    if (distanceItems.length > 1) {
        for (String distanceItem : distanceItems) {
            splitArray = distanceItem.split(" ");
            Log.e("distance List", splitArray[0]);
            distance = distance + Float.valueOf(splitArray[0]);
        }
        DecimalFormat decimalFormat = new DecimalFormat("#.##");
        float twoDigitsF = Float.valueOf(decimalFormat.format(distance));
        totalDis = String.valueOf(twoDigitsF) + " km";
        Log.e("Total km ", totalDis);
    } else {
        totalDis = distanceItems[0];
    }
    return totalDis;
}
Offside answered 9/12, 2017 at 6:15 Comment(0)
P
0

Here's my code.Pass the JSONObject obtained from direction request url.

HashMap<String,Object> getDistanceDuration(JSONObject jsonObject) {
    HashMap<String,Object> hashMap=new HashMap<>();
    double totalDistance = 0;
    long totalDuration = 0;
    try {
        JSONArray jRoutes = jsonObject.getJSONArray("routes");
        for (int i = 0; i < jRoutes.length(); i++) {
            JSONArray jLegs = ((JSONObject) jRoutes.get(i)).getJSONArray("legs");
            for (int j = 0; j < jLegs.length(); j++) {
                JSONObject legs1 = jLegs.getJSONObject(j);
                JSONObject distance = legs1.getJSONObject("distance");
                JSONObject duration = legs1.getJSONObject("duration");
                totalDistance = totalDistance+distance.getLong("value");
                totalDuration = totalDuration+duration.getLong("value");
            }
        }
        totalDistance/=1000;
        totalDuration/=60;
        totalDistance= Math.round(totalDistance* 10) / 10.0;
        hashMap.put("distance",totalDistance);
        hashMap.put("duration",totalDuration);
        Log.i("distance",totalDistance);
        Log.i("duration",totalDuration);

    } catch (JSONException e) {
        e.printStackTrace();
    }
    return hashMap;
}
Panda answered 1/4, 2020 at 10:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.