|
1 | 1 | use std::collections::BTreeMap;
|
2 | 2 |
|
3 | 3 | use re_chunk::TimelineName;
|
4 |
| -use re_entity_db::{TimeCounts, TimesPerTimeline}; |
| 4 | +use re_entity_db::{TimeCounts, TimelineStats, TimesPerTimeline}; |
5 | 5 | use re_log_types::{
|
6 | 6 | AbsoluteTimeRange, AbsoluteTimeRangeF, Duration, TimeCell, TimeInt, TimeReal, TimeType,
|
7 | 7 | Timeline,
|
@@ -564,7 +564,8 @@ impl TimeControl {
|
564 | 564 | if matches!(self.timeline, ActiveTimeline::Auto(_))
|
565 | 565 | || !is_timeline_valid(self.timeline(), times_per_timeline)
|
566 | 566 | {
|
567 |
| - self.timeline = ActiveTimeline::Auto(default_timeline(times_per_timeline.timelines())); |
| 567 | + self.timeline = |
| 568 | + ActiveTimeline::Auto(default_timeline(times_per_timeline.timelines_with_stats())); |
568 | 569 | }
|
569 | 570 | }
|
570 | 571 |
|
@@ -740,23 +741,26 @@ fn range(values: &TimeCounts) -> AbsoluteTimeRange {
|
740 | 741 | AbsoluteTimeRange::new(min(values), max(values))
|
741 | 742 | }
|
742 | 743 |
|
743 |
| -/// Pick the timeline that should be the default, prioritizing user-defined ones. |
744 |
| -fn default_timeline<'a>(timelines: impl IntoIterator<Item = &'a Timeline>) -> Timeline { |
745 |
| - let mut found_log_tick = false; |
746 |
| - let mut found_log_time = false; |
| 744 | +/// Pick the timeline that should be the default, by number of elements and prioritizing user-defined ones. |
| 745 | +fn default_timeline<'a>(timelines: impl IntoIterator<Item = &'a TimelineStats>) -> Timeline { |
| 746 | + re_tracing::profile_function!(); |
747 | 747 |
|
748 |
| - for timeline in timelines { |
749 |
| - if timeline == &Timeline::log_tick() { |
750 |
| - found_log_tick = true; |
751 |
| - } else if timeline == &Timeline::log_time() { |
752 |
| - found_log_time = true; |
753 |
| - } else { |
754 |
| - return *timeline; |
| 748 | + // Helper function that acts as a tie-breaker. |
| 749 | + fn timeline_priority(timeline: &Timeline) -> u8 { |
| 750 | + match timeline { |
| 751 | + t if *t == Timeline::log_tick() => 0, // lowest priority |
| 752 | + t if *t == Timeline::log_time() => 1, // medium priority |
| 753 | + _ => 2, // user-defined, highest priority |
755 | 754 | }
|
756 | 755 | }
|
| 756 | + let most_events = timelines.into_iter().max_by(|a, b| { |
| 757 | + a.num_events() |
| 758 | + .cmp(&b.num_events()) |
| 759 | + .then_with(|| timeline_priority(&a.timeline).cmp(&timeline_priority(&b.timeline))) |
| 760 | + }); |
757 | 761 |
|
758 |
| - if found_log_tick && !found_log_time { |
759 |
| - Timeline::log_tick() |
| 762 | + if let Some(most_events) = most_events { |
| 763 | + most_events.timeline |
760 | 764 | } else {
|
761 | 765 | Timeline::log_time()
|
762 | 766 | }
|
@@ -823,50 +827,62 @@ fn step_back_time_looped(
|
823 | 827 | mod tests {
|
824 | 828 | use super::*;
|
825 | 829 |
|
| 830 | + fn with_events(timeline: Timeline, num: u64) -> TimelineStats { |
| 831 | + TimelineStats { |
| 832 | + timeline, |
| 833 | + // Dummy `TimeInt` because were only interested in the counts. |
| 834 | + per_time: std::iter::once((TimeInt::ZERO, num)).collect(), |
| 835 | + total_count: num, |
| 836 | + } |
| 837 | + } |
| 838 | + |
826 | 839 | #[test]
|
827 | 840 | fn test_default_timeline() {
|
828 |
| - let log_time = Timeline::log_time(); |
829 |
| - let log_tick = Timeline::log_tick(); |
830 |
| - let custom_timeline0 = Timeline::new("my_timeline0", TimeType::DurationNs); |
831 |
| - let custom_timeline1 = Timeline::new("my_timeline1", TimeType::DurationNs); |
832 |
| - |
833 |
| - assert_eq!(default_timeline([]), log_time); |
834 |
| - assert_eq!(default_timeline([&log_tick]), log_tick); |
835 |
| - assert_eq!(default_timeline([&log_time]), log_time); |
836 |
| - assert_eq!(default_timeline([&log_time, &log_tick]), log_time); |
| 841 | + let log_time = with_events(Timeline::log_time(), 42); |
| 842 | + let log_tick = with_events(Timeline::log_tick(), 42); |
| 843 | + let custom_timeline0 = with_events(Timeline::new("my_timeline0", TimeType::DurationNs), 42); |
| 844 | + let custom_timeline1 = with_events(Timeline::new("my_timeline1", TimeType::DurationNs), 43); |
| 845 | + |
| 846 | + assert_eq!(default_timeline([]), log_time.timeline); |
| 847 | + assert_eq!(default_timeline([&log_tick]), log_tick.timeline); |
| 848 | + assert_eq!(default_timeline([&log_time]), log_time.timeline); |
| 849 | + assert_eq!(default_timeline([&log_time, &log_tick]), log_time.timeline); |
837 | 850 | assert_eq!(
|
838 | 851 | default_timeline([&log_time, &log_tick, &custom_timeline0]),
|
839 |
| - custom_timeline0 |
| 852 | + custom_timeline0.timeline |
840 | 853 | );
|
841 | 854 | assert_eq!(
|
842 | 855 | default_timeline([&custom_timeline0, &log_time, &log_tick]),
|
843 |
| - custom_timeline0 |
| 856 | + custom_timeline0.timeline |
844 | 857 | );
|
845 | 858 | assert_eq!(
|
846 | 859 | default_timeline([&log_time, &custom_timeline0, &log_tick]),
|
847 |
| - custom_timeline0 |
| 860 | + custom_timeline0.timeline |
848 | 861 | );
|
849 | 862 | assert_eq!(
|
850 | 863 | default_timeline([&custom_timeline0, &log_time]),
|
851 |
| - custom_timeline0 |
| 864 | + custom_timeline0.timeline |
852 | 865 | );
|
853 | 866 | assert_eq!(
|
854 | 867 | default_timeline([&custom_timeline0, &log_tick]),
|
855 |
| - custom_timeline0 |
| 868 | + custom_timeline0.timeline |
856 | 869 | );
|
857 | 870 | assert_eq!(
|
858 | 871 | default_timeline([&log_time, &custom_timeline0]),
|
859 |
| - custom_timeline0 |
| 872 | + custom_timeline0.timeline |
860 | 873 | );
|
861 | 874 | assert_eq!(
|
862 | 875 | default_timeline([&log_tick, &custom_timeline0]),
|
863 |
| - custom_timeline0 |
| 876 | + custom_timeline0.timeline |
864 | 877 | );
|
865 | 878 |
|
866 | 879 | assert_eq!(
|
867 | 880 | default_timeline([&custom_timeline0, &custom_timeline1]),
|
868 |
| - custom_timeline0 |
| 881 | + custom_timeline1.timeline |
| 882 | + ); |
| 883 | + assert_eq!( |
| 884 | + default_timeline([&custom_timeline0]), |
| 885 | + custom_timeline0.timeline |
869 | 886 | );
|
870 |
| - assert_eq!(default_timeline([&custom_timeline0]), custom_timeline0); |
871 | 887 | }
|
872 | 888 | }
|
0 commit comments