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.
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;
}