Doordash | Phone | Claim Scheduled Deliveries
Anonymous User
3141

Part 1:

At DoorDash, many deliveries are scheduled well in advance. To improve our assignment rate, we want to enable dashers to claim these scheduled deliveries early. However, we noticed that certain dashers perform better, and want to reward them with a better selection. As a simple solution, we will introduce open windows for when deliveries will appear for a particular dasher. Below are the following requirements.

  1. deliveries scheduled two days or further into the future should never be available
  2. high tier dashers can see all of next day deliveries if the current time is 18:00 or later
  3. all dashers can see all of next day deliveries if the current time is 19:00 or later
  4. all dashers can see same day deliveries anytime

Example:
deliveries = [
{ “id”: “one”, “pickupTime”: “2021/01/15 10:00”, “storeId”: “store_1” },
{ “id”: “two”, “pickupTime”: “2021/01/16 6:00”, “storeId”: “store_1” }
];

dasher = { “id”: “dasher_1”, “tier”: “low” };

getAvailableDeliveries(dasher, deliveries, 2021/01/15 18:00) -> [“one”]

class Delivery {
    final String id;
    final LocalDateTime pickupTime;
    final String storeId;

    public Delivery(String id, LocalDateTime pickupTime, String storeId) {
        this.id = id;
        this.pickupTime = pickupTime;
        this.storeId = storeId;
    }

    @Override
    public String toString() {
        return id;
    }
}

class Dasher {
    final String id;
    final String tier;  // “high” or “low"

    public Dasher(String id, String tier) {
        this.id = id;
        this.tier = tier;
    }
}

class StorePreference {
    final String id;
    final String storeId;
    final String dasherId;

    public StorePreference(String id, String storeId, String dasherId) {
        this.id = id;
        this.storeId = storeId;
        this.dasherId = dasherId;
    }
}

class Doordash {


    public boolean canDasherClaimDelivery(Dasher dasher, Delivery delivery, LocalDateTime dasherCurrentTime) {
        long days = DAYS.between(dasherCurrentTime.toLocalDate(), delivery.pickupTime.toLocalDate());

        final int dasherHour = dasherCurrentTime.getHour();

        if (days <= 0) {
            return true;
        }
        if (days > 1) {
            return false;
        }
        if (dasher.tier.equals("high") && dasherHour >= 18) {
            return true;
        }
        return dasherHour >= 19;
    }

    public List<Delivery> getAvailableDeliveries(Dasher dasher, List<Delivery> deliveries, LocalDateTime currentTime) {
        List<Delivery> list = new ArrayList<>();
        for (Delivery delivery : deliveries) {
            if (canDasherClaimDelivery(dasher, delivery, currentTime)) {
                list.add(delivery);
            }
        }
        return list;
    }
}

Followup:

We realized, some dashers work really well for some stores, but not as much for others. Therefore we want to allow stores the ability to prefer dashers, so that they can see and claim their deliveries first. Below, is the new requirement we want to introduce.
stores who prefer dashers will have their next day deliveries show up at 17:00 for those preferred dashers only

Consider this new class and new method signature:
class StorePreference {
string id;
string storeId;
string dasherId;
}

Example:
List getAvailableDeliveries(Dasher dasher, List Delivery, DateTime currentTime, List storePreferences)
deliveries = [{ one, 2021/01/15 10:00, store_1 }, { two, 2021/01/16 6:00, store_1 }]
dasher = { dasher_1, low }
preferences = [{ one, store_1, dasher_1 }]

getAvailableDeliveries(dasher, deliveries, 2021/01/15 18:00, preferences) should return both deliveries

class StorePreference {
    final String id;
    final String storeId;
    final String dasherId;

    public StorePreference(String id, String storeId, String dasherId) {
        this.id = id;
        this.storeId = storeId;
        this.dasherId = dasherId;
    }
}

public List<Delivery> getAvailableDeliveries(Dasher dasher, List<Delivery> deliveries, LocalDateTime currentTime, List<StorePreference> storePreferences) {
        List<Delivery> list = new ArrayList<>();

        Map<String, Set<String>> map = new HashMap<>();
        for (StorePreference obj : storePreferences) {
            Set<String> storeIds = map.getOrDefault(obj.dasherId, new HashSet<>());
            storeIds.add(obj.storeId);
            map.put(obj.dasherId, storeIds);
        }

        for (Delivery delivery : deliveries) {
            if (canDasherClaimDelivery(dasher, delivery, currentTime)) {
                list.add(delivery);
            }
        }
        return list;
    }

public boolean canDasherClaimDelivery(Dasher dasher, Delivery delivery, LocalDateTime dasherCurrentTime, Map<String, Set<String>> map) {
        long days = DAYS.between(dasherCurrentTime.toLocalDate(), delivery.pickupTime.toLocalDate());

        final int dasherHour = dasherCurrentTime.getHour();
        final String dasherId = dasher.id;
        final String storeId = delivery.storeId;
        
        if (map.containsKey(dasherId)) {
            Set<String> storeIds = map.get(dasherId);
            if (storeIds.contains(storeId)) {
                if (dasherHour >= 17) {
                    return true;
                }
            }
        }

        if (days <= 0) {
            return true;
        }
        if (days > 1) {
            return false;
        }
        if (dasher.tier.equals("high") && dasherHour >= 18) {
            return true;
        }
        return dasherHour >= 19;
    }
Comments (6)