Use cases
This section contains examples of settings for different scenarios of using Calendar Planning.
Planning by location and visit
You can plan routes in multiple ways:
-
If all location visits have the same type, specify a list of locations on the locations sheet, setting the following parameters for each location:
- Time windows.
- Handling time.
- Days of visits.
- Number and frequency of visits.
- Penalty for not visiting a location.
In this case, you don't need the visits sheet in the planning file.
-
If locations have different types of visits that must be completed in a specific sequence, they must be configured on the visits sheet. The handling time, penalty for not visiting a location, and days of visits are specified for all visit types on the visits sheet, while time windows as well as the number and frequency of visits are specified for an individual location as a whole on the locations sheet.
-
You can combine methods 1 and 2: specify visit types only for some locations and specify only location parameters for the rest of them.
Example 1
2 employees visit 20 locations. The handling time (service_duration_s
), days of visits (allowed_days
, preferred_days
, mandatory_days
, and denied_days
), penalties for skipping a visit (penalty.visit_count.per_visit
) and for skipping all visits (penalty.drop
) are set for them on the locations sheet.
API request (JSON) ⋅ API response
Example 2
The same as in example 1, but visit types are set for all locations on the visits sheet. The handling time (service_duration_s
), days of visits (allowed_days
, preferred_days
, and denied_days
), and a penalty for skipping a visit (drop
) are set for each visit type.
API request (JSON) ⋅ API response
Example 3
The same as in example 1, but locations 1 and 3 have set visit types on the visits sheet. For all other locations, visit types aren't set, and their parameters are specified only on the locations sheet.
API request (JSON) ⋅ API response
Location and visit priorities
You can prioritize visits to locations using the following methods:
- Specify priorities for some or all locations.
- Set penalties for not visiting locations depending on their priority.
- Specify optional tags with different weights for locations.
For each of these methods, you can additionally use the late_days_cost_increment
parameter to plan visits to priority locations on the earliest days.
Setting priorities
You can set priorities for visiting all or some locations directly using the priority
parameter on the locations
sheet. For more information, see Priorities.
Example
The planning involves 2 employees who need to visit 32 locations that have been assigned different priorities: 0, 1, or without priority.
As a result of planning, employees visit all locations with priority 0 or without priority. Locations with priority 1 remain unassigned.
API request (JSON) ⋅ API response
Prioritization using penalties
To prioritize locations and visits, you can impose penalties for not visiting locations and for skipping particular visit types. The higher the penalty, the more likely the location or visit being planned.
You can use the following parameters:
-
For locations — on the locations sheet:
penalty.drop
: Fixed penalty if no visits to the location have been planned.penalty.visit_count.fixed
: Fixed penalty if at least one visit to the location has been skipped.penalty.visit_count.per_visit
: Penalty for each skipped visit to the location.
-
For specific visit types — on the visits sheet, specify the
drop
parameter value (locations.visits.N.drop
in the API request). It will replace thepenalty.visit_count.per_visit
value for visits of this type.
For more information about the parameters used for planning visits, see Number and frequency of visits to locations and Visit types.
Example 1
The planning involves 2 employees who need to visit 32 locations with the same priority. Each location has a hard time window, so no delays or early arrivals are allowed. The penalty for not visiting a location is penalty.drop
= 0.
As a result of planning, employees never visit location 3 and skip several visits to locations 1 and 7.
API request (JSON) ⋅ API response
Example 2
The same as in example 1, but location 3 has a high priority, so its penalty.drop
= 1,000,000.
As a result of planning, employees visit location 3, and visits to locations 25 and 29 remain unassigned.
API request (JSON) ⋅ API response
Example 3
The same as in example 1, but the visits sheet contains drop
penalties for skipping different types of visits to location 1 in descending order of the visit type priority:
- 1,000,000: Inventory.
- 500,000: Ad installation.
- 100,000: Stocking.
As a result, all locations and visits are planned except for two stocking visits at location 1.
API request (JSON) ⋅ API response
Prioritization using tags
You can prioritize visits to a location using optional tags. To do this, open the locations sheet, then enter the tag name in the optional_tags.0.tag field and its weight (more than 0) in the optional_tags.0.value field. The greater the tag weight, the more likely a visit to these locations will be planned.
Example
2 employees need to visit 49 locations. 8 locations are marked with the optional VIP
tag with a weight of 3000.
As a result of planning, all VIP locations are distributed among employees, and some untagged locations remain unassigned.
API request (JSON) ⋅ API response
Visits on the earliest days
To visit priority locations on earlier days, you can set the late_days_cost_increment
parameter on the options sheet. To learn how this parameter works, see Visits on the earliest days.
Example 1
An employee needs to visit 40 locations, the late_days_cost_increment
parameter isn't used. As a result, visits to locations are planned for 5 days.
API request (JSON) ⋅ API response
Example 2
The same as in example 1, but the parameter late_days_cost_increment
on the options sheet is set to 1000. As a result, visits to locations are planned for 4 days.
API request (JSON) ⋅ API response
Visiting remote locations
One or multiple locations may be located far away from the others. In this case, the cost of visiting such a location may be higher than the penalty for not visiting it or skipping one of the visits, and the location will be unassigned. To avoid this, you can set higher penalties for remote locations on the locations sheet:
penalty.visit_count.per_visit
: For skipping one visit to the location.penalty.drop
: For skipping all visits.
The cost of visiting a location can consist of the employee's hourly rate, kilometers in the route, start of the shift (if an additional employee has to be sent to the remote location), and other parameters. For more information, see Cost of work and payouts to employees.
Example 1
2 employees visit 18 locations. One of them (Location 2) is a remote one. The penalty for not visiting a location drop
is 1000 for all locations, and the penalty for skipping a visit penalty.visit_count.per_visit
is 17. By default, the cost of an employee starting their shift cost.fixed
is 3000 — this is more than the total penalty for not visiting a location. As a result, the remote location remains unassigned.
API request (JSON) ⋅ API response
Example 2
The same as in example 1, but the penalty for skipping a visit penalty.visit_count.per_visit
to the remote location has been increased to 3500 — this is more than the cost of starting a route. As a result, on certain days, the second employee starts their shift specifically to visit the remote location.
API request (JSON) ⋅ API response
Planning based on employees' skills
Sometimes, locations need to be visited by an employee with special skills or equipment. To plan routes taking into account these requirements, use location and employee tags.
In the required_tags
field on the locations sheet, list comma-separated tags that determine the mandatory requirements for visiting a location. Optional requirements are specified in the optional_tags.N.tag
and optional_tags.N.value
fields. For more information, see Location tags.
If the employee meets the location requirements, list the appropriate tags in the tags field on the employees sheet. If the employee mustn't visit locations with specific tags, specify them in the excluded_tags field. For more information, see Employee tags.
Example
An employee must wear a uniform or have a thermal bag to visit some locations. Such locations have the uniform
and fridge
tags in the required_tags
field. Locations 7 and 12 should be visited by employees with a pharmacology degree, so these locations have the optional pharmacy
tag. Employee 1 has no relevant education, so the pharmacy
tag is specified in the excluded_tags field for them.
As a result of planning, locations with special requirements are distributed among employees with the corresponding tags. Employee 1 visits locations that don't have the optional pharmacy
tag.
API request (JSON) ⋅ API response
Dense routes
To help employees spend less time traveling between locations, plan routes where locations are as close to each other as possible. There are two ways to do this:
- Using the
global_proximity_factor
anddaily_proximity_factor
density parameters. - Using restrictions on route segments and factors for starting and end segments.
Density parameters
For employees to visit nearby locations sequentially, use the following parameters:
global_proximity_factor
: Density parameter for the entire planning period.daily_proximity_factor
: Density parameter for a day.
You can set these parameters globally for all employees on the options sheet or individually for specific employees on the employees sheet.
Density parameters can take a value between 0 and 10, where 0 means no density, and 10 means maximum density. The recommended value range is from 0 to 1 (0 by default).
For more information, see Route density.
Example
Locations are primarily in the center, north, and south of the city. For routes to be more dense, global_proximity_factor
was set to 0.2 and daily_proximity_factor
was set to 0.5.
This resulted in the employees' routes becoming more geographically grouped.
API request (JSON) ⋅ API response
Route segment restrictions
You can set restrictions on the distance between neighboring locations or the travel time between them on the employees sheet using the max_edge_distance_m
and max_edge_duration_s
parameters, respectively. If you want the algorithm to consider the first and last segments of the route at a special cost under the given restrictions, specify positive factors for them in the first_edges_penalty_factor
and last_edges_penalty_factor
fields for mileage on the first and last route segments, respectively.
For more information, see Route segment restrictions and Starting and end route segments.
Example
Locations are primarily in the center, north, and south of the city. The restriction of 15,000 m is set on the maximum distance between neighboring locations. In addition, increasing factors (first_edges_penalty_factor
and last_edges_penalty_factor
of 4) are specified.
This results in the employees' routes becoming more geographically grouped.
API request (JSON) ⋅ API response
Assigning a location to an employee
To ensure that a location is always visited by the same employee, you can assign it to that employee using one of the following methods:
- Using location tags and employee tags.
- Using allowed and forbidden geofences.
Assigning a location using tags
You need to set a unique tag for the employee in the tags
field on the employees sheet. For all locations that must be assigned to this employee, you must specify this tag in the required_tags
field on the locations sheet.
Example
Visits to 50 locations can be distributed among 5 employees. Locations 40 and 50 have a unique tag of employee3
in the required_tags
field. Employee 3 has this tag in the tags
field as well. As a result, visits to locations 40 and 50 are assigned to this employee.
API request (JSON) ⋅ API response
Assigning a location using geofences
If you need to assign all locations in a certain area of the city to an employee, you can use allowed and forbidden geofences.
To allow only a specific employee to visit locations in a geofence, specify the geofence name on the employees sheet:
- For the selected employee, in the
allowed_zones
field. - For other employees, in the
forbidden_zones
field.
You can add new geofences via the interface and the API.
Example
Visits to 50 locations can be distributed among 5 employees. There's a geofence called North, which includes locations in the north of Moscow. This geofence is specified in the allowed_zones
field for employee 2 and in the forbidden_zones
field for other employees. As a result, visits to all locations within the North geofence are planned for employee 2.
API request (JSON) ⋅ API response
Workload balancing
During planning, locations aren't always evenly distributed among employees. To distribute the workload equally among employees, use the balancing parameters:
-
Add the
shipment_size.units
field (estimating the labor costs per one visit to a location) to the locations sheet. Labor costs are estimated in units.Note
If the handling time
service_duration_s
varies between locations, the estimation of labor costsshipment_size.units
must be proportional toservice_duration_s
. For example, if you setservice_duration_s
= 1800 andshipment_size.units
= 10 for a specific location, then theshipment_size.units
value forservice_duration_s
= 3600 must be 20. -
Multiply
shipment_size.units
byvisit_count
for each location. You'll get an estimate of labor costs for all visits to the location within the planning period. -
Sum up values for all locations. Divide the total amount by the number of days within the planning period (the
planning_days
field on the options sheet). You'll get an estimate of the labor costs for all visits to the location per day. -
Divide the total daily estimate of the labor costs by the number of employees. You'll get the average workload per employee per day.
-
Round up the resulting average workload and add extra 5–10 units. For example, if you get a value of 19.35, round it up to 20 and add 10 more units. The final result is 30 units. Add the
capacity.units
field to the employees sheet and specify the calculated value for all employees. -
On the employees sheet, specify the cost of one day of downtime (
cost.empty_run
) for each employee so that the algorithm takes all employees into account during planning. For example,cost.empty_run
= 100,000.
The workload will be distributed evenly among all employees during planning.
Example 1
Visits to 20 locations must be distributed among 3 employees. The balancing parameters aren't set. As a result, visits to all locations are assigned to employee 2. Employees 1 and 3 remain unassigned.
API request (JSON) ⋅ API response
Example 2
The same as in example 1, except this time the balancing parameters are set.
The labor costs for one visit to a location are estimated at 10 units. This value is indicated in the shipment_size.units
field on the locations sheet. 2 visits are planned for each location: visit_count
= 2.
The total labor cost estimate for all 20 locations is (10 * 2) * 20 = 400. This estimate is divided by the number of days within the planning period: 400 : 7 = 57.14.
The daily workload is distributed among 3 employees: 57.14 : 3 = 19.05. The value is rounded up and increased by 10, to 30 units. This estimate is specified for each employee in the capacity.units
field on the employees sheet. The cost of one day of downtime is also set for each employee: cost.empty_run
= 10,000.
As a result, visits to all locations are distributed evenly among all three employees.
API request (JSON) ⋅ API response