Skip to main content

valhalla_client/costing/
auto.rs

1//! Auto Costing Options
2use serde::Serialize;
3
4#[serde_with::skip_serializing_none]
5#[derive(Serialize, Debug, Clone, Default, PartialEq)]
6struct AutoCostingOptionsInner {
7    maneuver_penalty: Option<f32>,
8    gate_cost: Option<f32>,
9    gate_penalty: Option<f32>,
10    private_access_penalty: Option<f32>,
11    destination_only_penalty: Option<f32>,
12    toll_booth_cost: Option<f32>,
13    toll_booth_penalty: Option<f32>,
14    ferry_cost: Option<f32>,
15    use_ferry: Option<f32>,
16    use_highways: Option<f32>,
17    use_tolls: Option<f32>,
18    use_living_streets: Option<f32>,
19    use_tracks: Option<f32>,
20    service_penalty: Option<f32>,
21    service_factor: Option<f32>,
22    country_crossing_cost: Option<f32>,
23    country_crossing_penalty: Option<f32>,
24    shortest: Option<bool>,
25    use_distance: Option<f32>,
26    disable_hierarchy_pruning: Option<bool>,
27    top_speed: Option<f32>,
28    fixed_speed: Option<u32>,
29    closure_factor: Option<f32>,
30    ignore_closures: Option<bool>,
31    ignore_restrictions: Option<bool>,
32    ignore_oneways: Option<bool>,
33    ignore_non_vehicular_restrictions: Option<bool>,
34    ignore_access: Option<bool>,
35    // -- ↓ auto/taxi/bus only ↓ --
36    speed_types: Option<UsedSpeedSources>,
37    height: Option<f32>,
38    width: Option<f32>,
39    exclude_unpaved: Option<bool>,
40    exclude_cash_only_tolls: Option<bool>,
41    include_hov2: Option<bool>,
42    include_hov3: Option<bool>,
43    include_hot: Option<bool>,
44}
45
46#[derive(Serialize, Debug, Clone, Default, PartialEq)]
47/// Auto Costing Options
48pub struct AutoCostingOptions {
49    auto: AutoCostingOptionsInner,
50}
51impl AutoCostingOptions {
52    #[must_use]
53    /// Creates a new instance of [`AutoCostingOptions`].
54    pub fn builder() -> Self {
55        Self::default()
56    }
57
58    /// A cost applied when a [gate](http://wiki.openstreetmap.org/wiki/Tag:barrier%3Dgate) with
59    /// undefined or private access is encountered.
60    ///
61    /// This cost is added to the estimated time / elapsed time.
62    ///
63    /// Default: `30` seconds
64    pub fn gate_cost(mut self, gate_cost: f32) -> Self {
65        self.auto.gate_cost = Some(gate_cost);
66        self
67    }
68    /// A penalty applied when a [gate](https://wiki.openstreetmap.org/wiki/Tag:barrier%3Dgate) with
69    /// no access information is on the road.
70    ///
71    /// Default: `300` seconds
72    pub fn gate_penalty(mut self, gate_penalty: f32) -> Self {
73        self.auto.gate_penalty = Some(gate_penalty);
74        self
75    }
76    /// A penalty applied when a [gate](https://wiki.openstreetmap.org/wiki/Tag:barrier%3Dgate) or
77    /// [bollard](https://wiki.openstreetmap.org/wiki/Tag:barrier%3Dbollard) with `access=private`
78    /// is encountered.
79    ///
80    /// Default: `450` seconds
81    pub fn private_access_penalty(mut self, private_access_penalty: f32) -> Self {
82        self.auto.private_access_penalty = Some(private_access_penalty);
83        self
84    }
85    /// A penalty applied when entering a road which is only allowed to enter if necessary to reach
86    /// the [destination](https://wiki.openstreetmap.org/wiki/Tag:vehicle%3Ddestination).
87    pub fn destination_only_penalty(mut self, destination_only_penalty: f32) -> Self {
88        self.auto.destination_only_penalty = Some(destination_only_penalty);
89        self
90    }
91    /// A cost applied when a [toll booth](http://wiki.openstreetmap.org/wiki/Tag:barrier%3Dtoll_booth)
92    /// is encountered.
93    ///
94    /// This cost is added to the estimated and elapsed times.
95    ///
96    /// Default: `15` seconds
97    pub fn toll_booth_cost(mut self, toll_booth_cost: f32) -> Self {
98        self.auto.toll_booth_cost = Some(toll_booth_cost);
99        self
100    }
101    /// A penalty applied to the cost when a
102    /// [toll booth](http://wiki.openstreetmap.org/wiki/Tag:barrier%3Dtoll_booth) is encountered.
103    ///
104    /// This penalty can be used to create paths that avoid toll roads.
105    ///
106    /// Default: `0`
107    pub fn toll_booth_penalty(mut self, toll_booth_penalty: f32) -> Self {
108        self.auto.toll_booth_penalty = Some(toll_booth_penalty);
109        self
110    }
111    /// A cost applied when entering a ferry.
112    ///
113    /// This cost is added to the estimated and elapsed times.
114    ///
115    /// Default: `300` seconds (5 minutes)
116    pub fn ferry_cost(mut self, ferry_cost: f32) -> Self {
117        self.auto.ferry_cost = Some(ferry_cost);
118        self
119    }
120    /// This value indicates the willingness to take ferries.
121    ///
122    /// This is a range of values between `0` and `1`:
123    /// - Values near `0` attempt to avoid ferries and
124    /// - values near `1` will favor ferries.
125    ///
126    /// **Note:** sometimes ferries are required to complete a route so values of `0` are not guaranteed to avoid ferries entirely.
127    ///
128    /// Default: `0.5`
129    pub fn use_ferry(mut self, use_ferry: f32) -> Self {
130        debug_assert!(use_ferry >= 0.0);
131        debug_assert!(use_ferry <= 1.0);
132        self.auto.use_ferry = Some(use_ferry);
133        self
134    }
135    /// This value indicates the willingness to take highways.
136    ///
137    /// This is a range of values between `0` and 1:
138    /// - Values near `0` attempt to avoid highways and
139    /// - values near `1` will favor highways.
140    ///
141    /// **Note:** sometimes highways are required to complete a route so values of `0` are not guaranteed to avoid highways entirely.
142    ///
143    /// Default: `1.0`
144    pub fn use_highways(mut self, use_highways: f32) -> Self {
145        debug_assert!(use_highways >= 0.0);
146        debug_assert!(use_highways <= 1.0);
147        self.auto.use_highways = Some(use_highways);
148        self
149    }
150    /// This value indicates the willingness to take roads with tolls.
151    ///
152    /// This is a range of values between `0` and 1:
153    /// - Values near `0` attempt to avoid tolls and
154    /// - values near `1` will not attempt to avoid them.
155    ///
156    /// **Note:** sometimes roads with tolls are required to complete a route so values of `0` are not guaranteed to avoid them entirely.
157    ///
158    /// Default: `0.5`
159    pub fn use_tolls(mut self, use_tolls: f32) -> Self {
160        debug_assert!(use_tolls >= 0.0);
161        debug_assert!(use_tolls <= 1.0);
162        self.auto.use_tolls = Some(use_tolls);
163        self
164    }
165    /// This value indicates the willingness to take living streets.
166    ///
167    /// This is a range of values between `0` and 1:
168    /// - Values near `0` attempt to avoid living streets and
169    /// - values near `1` will favor living streets.
170    ///
171    /// **Note:** sometimes living streets are required to complete a route so values of `0` are not guaranteed to avoid living streets entirely.
172    ///
173    /// Default:
174    /// - `truck`: `0`
175    /// - `cars`/`buses`/`motor scooters`/`motorcycles`: `0.1`
176    pub fn use_living_streets(mut self, use_living_streets: f32) -> Self {
177        debug_assert!(use_living_streets >= 0.0);
178        debug_assert!(use_living_streets <= 1.0);
179        self.auto.use_living_streets = Some(use_living_streets);
180        self
181    }
182    /// This value indicates the willingness to take track roads.
183    ///
184    /// This is a range of values between `0` and 1:
185    /// - Values near `0` attempt to avoid tracks and
186    /// - values near `1` will favor tracks a little bit.
187    ///
188    /// **Note:** sometimes tracks are required to complete a route so values of `0` are not guaranteed to avoid tracks entirely.
189    ///
190    /// Default:
191    /// - `0` for autos,
192    /// - `0.5` for motor scooters and motorcycles.
193    pub fn use_tracks(mut self, use_tracks: f32) -> Self {
194        debug_assert!(use_tracks >= 0.0);
195        debug_assert!(use_tracks <= 1.0);
196        self.auto.use_tracks = Some(use_tracks);
197        self
198    }
199    /// A penalty applied for transition to generic service road.
200    ///
201    /// Default:
202    /// - `0` trucks and
203    /// - `15` for cars, buses, motor scooters and motorcycles.
204    pub fn service_penalty(mut self, service_penalty: f32) -> Self {
205        self.auto.service_penalty = Some(service_penalty);
206        self
207    }
208    /// A factor that modifies (multiplies) the cost when generic service roads are encountered.
209    ///
210    /// Default: `1`
211    pub fn service_factor(mut self, service_factor: f32) -> Self {
212        self.auto.service_factor = Some(service_factor);
213        self
214    }
215    /// A cost applied when encountering an international border.
216    ///
217    /// This cost is added to the estimated and elapsed times.
218    ///
219    /// Default: `600` seconds
220    pub fn country_crossing_cost(mut self, country_crossing_cost: f32) -> Self {
221        self.auto.country_crossing_cost = Some(country_crossing_cost);
222        self
223    }
224    /// A penalty applied for a country crossing.
225    ///
226    /// This penalty can be used to create paths that avoid spanning country boundaries.
227    ///
228    /// Default: `0`
229    pub fn country_crossing_penalty(mut self, country_crossing_penalty: f32) -> Self {
230        self.auto.country_crossing_penalty = Some(country_crossing_penalty);
231        self
232    }
233    /// Changes the metric to quasi-shortest, i.e. **purely distance-based costing**.
234    ///
235    /// Disables ALL other costings & penalties.
236    /// Also note, shortest will not disable hierarchy pruning, leading to potentially sub-optimal
237    /// routes for some costing models.
238    ///
239    /// Default: `false`
240    pub fn only_consider_quasi_shortest(mut self) -> Self {
241        self.auto.shortest = Some(true);
242        self
243    }
244
245    /// A factor that allows controlling the contribution of distance and time to the route costs.
246    ///
247    /// The value is in range between `0` and 1, where
248    /// - `0` only takes time into account (default),
249    /// - `0.5` will weight them roughly equally
250    /// - `1` only distance.
251    ///
252    /// **Note:** this costing is currently only available for [`super::Costing::Auto`].
253    pub fn use_distance(mut self, use_distance: f32) -> Self {
254        debug_assert!(use_distance >= 0.0);
255        debug_assert!(use_distance <= 1.0);
256        self.auto.use_distance = Some(use_distance);
257        self
258    }
259    /// Disable hierarchies to calculate the actual optimal route.
260    ///
261    /// **Note:** This could be quite a performance drainer so there is an upper limit of distance.
262    /// If the upper limit is exceeded, this option will always be `false`.
263    ///
264    /// Default: `false`
265    pub fn disable_hierarchy_pruning(mut self) -> Self {
266        self.auto.disable_hierarchy_pruning = Some(true);
267        self
268    }
269    /// Top speed the vehicle can go.
270    ///
271    /// Also used to avoid roads with higher speeds than this value.
272    /// Must be between `10` and `252 KPH`.
273    ///
274    /// Default:
275    /// - `truck`: `120 KPH`
276    /// - `auto`/`bus`: `140 KPH`
277    pub fn top_speed(mut self, top_speed: f32) -> Self {
278        debug_assert!(top_speed >= 10.0);
279        debug_assert!(top_speed <= 252.0);
280        self.auto.top_speed = Some(top_speed);
281        self
282    }
283    /// Fixed speed the vehicle can go. Used to override the calculated speed.
284    ///
285    /// Can be useful if speed of vehicle is known.
286    /// Must be between `1` and `252 KPH`.
287    ///
288    /// Default: `0KPH` which disables fixed speed and falls back to the standard calculated speed
289    /// based on the road attribution.
290    pub fn fixed_speed(mut self, fixed_speed: u32) -> Self {
291        debug_assert!(fixed_speed >= 1);
292        debug_assert!(fixed_speed <= 252);
293        self.auto.fixed_speed = Some(fixed_speed);
294        self
295    }
296    /// A factor that penalizes the cost when traversing a closed edge
297    ///
298    /// Example:
299    /// If `search_filter.exclude_closures` is `false` for origin and/or destination
300    /// location and the route starts/ends on closed edges.
301    ///
302    /// Its value can range from
303    /// - `1.0` don't penalize closed edges,
304    /// - to `10.0` apply high cost penalty to closed edges.
305    ///
306    /// **Note:** This factor is applicable only for motorized modes of transport, i.e `auto`, `motorcycle`, `motor_scooter`, `bus`, `truck` & `taxi`.
307    ///
308    /// Default: `9.0`
309    pub fn closure_factor(mut self, closure_factor: f32) -> Self {
310        self.auto.closure_factor = Some(closure_factor);
311        self
312    }
313    /// If set ignores all closures, marked due to live traffic closures, during routing.
314    ///
315    /// **Note:** This option cannot be set if `location.search_filter.exclude_closures` is also
316    /// specified in the request and will return an error if it is
317    pub fn ignore_closures(mut self) -> Self {
318        self.auto.ignore_closures = Some(true);
319        self
320    }
321    /// If set, ignores any restrictions (e.g. turn/dimensional/conditional restrictions).
322    ///
323    /// Especially useful for matching GPS traces to the road network regardless of restrictions.
324    ///
325    /// Default: `false`
326    pub fn ignore_restrictions(mut self) -> Self {
327        self.auto.ignore_restrictions = Some(true);
328        self
329    }
330    /// If set, ignores one-way restrictions.
331    ///
332    /// Especially useful for matching GPS traces to the road network ignoring uni-directional traffic rules.
333    /// Not included in [`Self::ignore_restrictions`] option.
334    ///
335    /// Default: `false`
336    pub fn ignore_oneways(mut self) -> Self {
337        self.auto.ignore_oneways = Some(true);
338        self
339    }
340    /// Similar to [`Self::ignore_restrictions`], but will respect restrictions that impact vehicle safety,
341    /// such as weight and size restrictions.
342    ///
343    /// Default: `false`
344    pub fn ignore_non_vehicular_restrictions(mut self) -> Self {
345        self.auto.ignore_non_vehicular_restrictions = Some(true);
346        self
347    }
348    /// Ignore mode-specific access tags.
349    ///
350    /// Especially useful for matching GPS traces to the road network regardless of restrictions.
351    ///
352    /// Default `false`
353    pub fn ignore_access(mut self) -> Self {
354        self.auto.ignore_access = Some(true);
355        self
356    }
357    /// Will determine which speed sources are used, if available.
358    ///
359    /// A list of strings with the following possible values:
360    /// - [`UsedSpeedSources::All`]
361    /// - [`UsedSpeedSources::Freeflow`]
362    /// - [`UsedSpeedSources::Constrained`]
363    /// - [`UsedSpeedSources::Predicted`]
364    /// - [`UsedSpeedSources::Current`]
365    ///
366    /// Default: [`UsedSpeedSources::All`] sources (again, only if available)
367    pub fn speed_types(mut self, speed_types: UsedSpeedSources) -> Self {
368        if speed_types == UsedSpeedSources::All {
369            self.auto.speed_types = None
370        } else {
371            self.auto.speed_types = Some(speed_types);
372        }
373        self
374    }
375
376    /// The height of the vehicle (in meters).
377    ///
378    /// Default:
379    /// - `car`/`bus`/`taxi`: `1.9` and
380    /// - `truck`: `4.11`
381    pub fn height(mut self, height: f32) -> Self {
382        self.auto.height = Some(height);
383        self
384    }
385    /// The width of the vehicle (in meters).
386    ///
387    /// Default:
388    /// - `car`/`bus`/`taxi`: `1.6` and
389    /// - `truck`: `2.6`
390    pub fn width(mut self, width: f32) -> Self {
391        self.auto.width = Some(width);
392        self
393    }
394    /// Exclude unpaved roads.
395    ///
396    /// If exclude_unpaved is set it is allowed to start and end with unpaved roads,
397    /// but is not allowed to have them in the middle of the route path,
398    /// otherwise they are allowed.
399    ///
400    /// Default: `false`.
401    pub fn exclude_unpaved(mut self) -> Self {
402        self.auto.exclude_unpaved = Some(true);
403        self
404    }
405    /// Desire to avoid routes with cash-only tolls.
406    ///
407    /// Default: `false`.
408    pub fn exclude_cash_only_tolls(mut self, exclude_cash_only_tolls: bool) -> Self {
409        self.auto.exclude_cash_only_tolls = Some(exclude_cash_only_tolls);
410        self
411    }
412    /// Include HOV roads with a 2-occupant requirement in the route when advantageous.
413    ///
414    /// Default: `false`.
415    pub fn include_hov2(mut self, include_hov2: bool) -> Self {
416        self.auto.include_hov2 = Some(include_hov2);
417        self
418    }
419    /// Include HOV roads with a 3-occupant requirement in the route when advantageous.
420    ///
421    /// Default: `false`.
422    pub fn include_hov3(mut self, include_hov3: bool) -> Self {
423        self.auto.include_hov3 = Some(include_hov3);
424        self
425    }
426    /// Include tolled HOV roads which require the driver to pay a toll if the occupant requirement isn't met.
427    ///
428    /// Default: `false`.
429    pub fn include_hot(mut self, include_hot: bool) -> Self {
430        self.auto.include_hot = Some(include_hot);
431        self
432    }
433}
434
435#[derive(Serialize, Debug, Clone, Copy, Eq, PartialEq)]
436/// Used Speed Sources
437pub enum UsedSpeedSources {
438    #[serde(rename = "all")]
439    /// All speed sources
440    All,
441    #[serde(rename = "freeflow")]
442    /// Freeflow speed
443    Freeflow,
444    #[serde(rename = "constrained")]
445    /// Constrained speed
446    Constrained,
447    #[serde(rename = "predicted")]
448    /// Predicted speed
449    Predicted,
450    #[serde(rename = "current")]
451    /// Current speed
452    Current,
453}
454#[cfg(test)]
455mod test {
456    use super::*;
457    #[test]
458    fn serialisation() {
459        assert_eq!(
460            serde_json::to_value(AutoCostingOptions::default()).unwrap(),
461            serde_json::json!({"auto":{}})
462        );
463    }
464
465    #[test]
466    fn builder_returns_default() {
467        assert_eq!(AutoCostingOptions::builder(), AutoCostingOptions::default());
468    }
469
470    #[test]
471    fn gate_cost_sets_value() {
472        let opts = AutoCostingOptions::builder().gate_cost(45.0);
473        assert_eq!(opts.auto.gate_cost, Some(45.0));
474    }
475
476    #[test]
477    fn gate_penalty_sets_value() {
478        let opts = AutoCostingOptions::builder().gate_penalty(500.0);
479        assert_eq!(opts.auto.gate_penalty, Some(500.0));
480    }
481
482    #[test]
483    fn private_access_penalty_sets_value() {
484        let opts = AutoCostingOptions::builder().private_access_penalty(600.0);
485        assert_eq!(opts.auto.private_access_penalty, Some(600.0));
486    }
487
488    #[test]
489    fn destination_only_penalty_sets_value() {
490        let opts = AutoCostingOptions::builder().destination_only_penalty(100.0);
491        assert_eq!(opts.auto.destination_only_penalty, Some(100.0));
492    }
493
494    #[test]
495    fn toll_booth_cost_sets_value() {
496        let opts = AutoCostingOptions::builder().toll_booth_cost(20.0);
497        assert_eq!(opts.auto.toll_booth_cost, Some(20.0));
498    }
499
500    #[test]
501    fn toll_booth_penalty_sets_value() {
502        let opts = AutoCostingOptions::builder().toll_booth_penalty(250.0);
503        assert_eq!(opts.auto.toll_booth_penalty, Some(250.0));
504    }
505
506    #[test]
507    fn ferry_cost_sets_value() {
508        let opts = AutoCostingOptions::builder().ferry_cost(400.0);
509        assert_eq!(opts.auto.ferry_cost, Some(400.0));
510    }
511
512    #[test]
513    fn use_ferry_sets_value() {
514        let opts = AutoCostingOptions::builder().use_ferry(0.5);
515        assert_eq!(opts.auto.use_ferry, Some(0.5));
516    }
517
518    #[test]
519    fn use_highways_sets_value() {
520        let opts = AutoCostingOptions::builder().use_highways(0.8);
521        assert_eq!(opts.auto.use_highways, Some(0.8));
522    }
523
524    #[test]
525    fn use_tolls_sets_value() {
526        let opts = AutoCostingOptions::builder().use_tolls(0.3);
527        assert_eq!(opts.auto.use_tolls, Some(0.3));
528    }
529
530    #[test]
531    fn use_living_streets_sets_value() {
532        let opts = AutoCostingOptions::builder().use_living_streets(0.6);
533        assert_eq!(opts.auto.use_living_streets, Some(0.6));
534    }
535
536    #[test]
537    fn use_tracks_sets_value() {
538        let opts = AutoCostingOptions::builder().use_tracks(0.2);
539        assert_eq!(opts.auto.use_tracks, Some(0.2));
540    }
541
542    #[test]
543    fn service_penalty_sets_value() {
544        let opts = AutoCostingOptions::builder().service_penalty(10.0);
545        assert_eq!(opts.auto.service_penalty, Some(10.0));
546    }
547
548    #[test]
549    fn service_factor_sets_value() {
550        let opts = AutoCostingOptions::builder().service_factor(1.5);
551        assert_eq!(opts.auto.service_factor, Some(1.5));
552    }
553
554    #[test]
555    fn country_crossing_cost_sets_value() {
556        let opts = AutoCostingOptions::builder().country_crossing_cost(600.0);
557        assert_eq!(opts.auto.country_crossing_cost, Some(600.0));
558    }
559
560    #[test]
561    fn country_crossing_penalty_sets_value() {
562        let opts = AutoCostingOptions::builder().country_crossing_penalty(0.0);
563        assert_eq!(opts.auto.country_crossing_penalty, Some(0.0));
564    }
565
566    #[test]
567    fn use_distance_sets_value() {
568        let opts = AutoCostingOptions::builder().use_distance(0.9);
569        assert_eq!(opts.auto.use_distance, Some(0.9));
570    }
571
572    #[test]
573    fn disable_hierarchy_pruning_sets_value() {
574        let opts = AutoCostingOptions::builder().disable_hierarchy_pruning();
575        assert_eq!(opts.auto.disable_hierarchy_pruning, Some(true));
576    }
577
578    #[test]
579    fn only_consider_quasi_shortest_sets_value() {
580        let opts = AutoCostingOptions::builder().only_consider_quasi_shortest();
581        assert_eq!(opts.auto.shortest, Some(true));
582    }
583
584    #[test]
585    fn top_speed_sets_value() {
586        let opts = AutoCostingOptions::builder().top_speed(120.0);
587        assert_eq!(opts.auto.top_speed, Some(120.0));
588    }
589
590    #[test]
591    fn fixed_speed_sets_value() {
592        let opts = AutoCostingOptions::builder().fixed_speed(80);
593        assert_eq!(opts.auto.fixed_speed, Some(80));
594    }
595
596    #[test]
597    fn closure_factor_sets_value() {
598        let opts = AutoCostingOptions::builder().closure_factor(5.0);
599        assert_eq!(opts.auto.closure_factor, Some(5.0));
600    }
601
602    #[test]
603    fn ignore_closures_sets_value() {
604        let opts = AutoCostingOptions::builder().ignore_closures();
605        assert_eq!(opts.auto.ignore_closures, Some(true));
606    }
607
608    #[test]
609    fn ignore_restrictions_sets_value() {
610        let opts = AutoCostingOptions::builder().ignore_restrictions();
611        assert_eq!(opts.auto.ignore_restrictions, Some(true));
612    }
613
614    #[test]
615    fn ignore_oneways_sets_value() {
616        let opts = AutoCostingOptions::builder().ignore_oneways();
617        assert_eq!(opts.auto.ignore_oneways, Some(true));
618    }
619
620    #[test]
621    fn ignore_non_vehicular_restrictions_sets_value() {
622        let opts = AutoCostingOptions::builder().ignore_non_vehicular_restrictions();
623        assert_eq!(opts.auto.ignore_non_vehicular_restrictions, Some(true));
624    }
625
626    #[test]
627    fn ignore_access_sets_value() {
628        let opts = AutoCostingOptions::builder().ignore_access();
629        assert_eq!(opts.auto.ignore_access, Some(true));
630    }
631
632    #[test]
633    fn speed_types_sets_value() {
634        let opts = AutoCostingOptions::builder().speed_types(UsedSpeedSources::Freeflow);
635        assert_eq!(opts.auto.speed_types, Some(UsedSpeedSources::Freeflow));
636    }
637
638    #[test]
639    fn height_sets_value() {
640        let opts = AutoCostingOptions::builder().height(3.5);
641        assert_eq!(opts.auto.height, Some(3.5));
642    }
643
644    #[test]
645    fn width_sets_value() {
646        let opts = AutoCostingOptions::builder().width(2.5);
647        assert_eq!(opts.auto.width, Some(2.5));
648    }
649
650    #[test]
651    fn exclude_unpaved_sets_value() {
652        let opts = AutoCostingOptions::builder().exclude_unpaved();
653        assert_eq!(opts.auto.exclude_unpaved, Some(true));
654    }
655
656    #[test]
657    fn exclude_cash_only_tolls_sets_value() {
658        let opts = AutoCostingOptions::builder().exclude_cash_only_tolls(true);
659        assert_eq!(opts.auto.exclude_cash_only_tolls, Some(true));
660    }
661
662    #[test]
663    fn include_hov2_sets_value() {
664        let opts = AutoCostingOptions::builder().include_hov2(true);
665        assert_eq!(opts.auto.include_hov2, Some(true));
666    }
667
668    #[test]
669    fn include_hov3_sets_value() {
670        let opts = AutoCostingOptions::builder().include_hov3(true);
671        assert_eq!(opts.auto.include_hov3, Some(true));
672    }
673
674    #[test]
675    fn include_hot_sets_value() {
676        let opts = AutoCostingOptions::builder().include_hot(true);
677        assert_eq!(opts.auto.include_hot, Some(true));
678    }
679
680    #[test]
681    fn chaining_works() {
682        let opts = AutoCostingOptions::builder()
683            .gate_cost(45.0)
684            .use_highways(0.8)
685            .top_speed(120.0);
686        assert_eq!(opts.auto.gate_cost, Some(45.0));
687        assert_eq!(opts.auto.use_highways, Some(0.8));
688        assert_eq!(opts.auto.top_speed, Some(120.0));
689    }
690}