use std::collections::HashMap;
use crate::{MatchConfig, RouteGroup};
#[cfg(not(feature = "parallel"))]
use crate::group_signatures;
#[cfg(feature = "parallel")]
use crate::{group_incremental, group_signatures_parallel};
use super::activity_store::ActivityStore;
use super::signature_store::SignatureStore;
#[derive(Debug, Default)]
pub struct RouteGrouper {
groups: Vec<RouteGroup>,
route_names: HashMap<String, String>,
dirty: bool,
}
impl RouteGrouper {
pub fn new() -> Self {
Self {
groups: Vec::new(),
route_names: HashMap::new(),
dirty: false,
}
}
pub fn mark_dirty(&mut self) {
self.dirty = true;
}
pub fn is_dirty(&self) -> bool {
self.dirty
}
pub fn invalidate(&mut self) {
self.groups.clear();
self.dirty = true;
}
pub fn clear(&mut self) {
self.groups.clear();
self.route_names.clear();
self.dirty = false;
}
pub fn ensure_computed(
&mut self,
cache: &mut SignatureStore,
store: &ActivityStore,
config: &MatchConfig,
) {
if !self.dirty {
return;
}
cache.ensure_computed(store, config);
#[cfg(feature = "parallel")]
{
let can_use_incremental = !self.groups.is_empty()
&& cache.has_newly_computed()
&& cache.len() > cache.newly_computed_count();
if can_use_incremental {
let new_sigs = cache.newly_computed();
let existing_sigs = cache.existing();
self.groups = group_incremental(&new_sigs, &self.groups, &existing_sigs, config);
} else {
let signatures = cache.all_cloned();
self.groups = group_signatures_parallel(&signatures, config);
}
}
#[cfg(not(feature = "parallel"))]
{
let signatures = cache.all_cloned();
self.groups = group_signatures(&signatures, config);
}
cache.clear_newly_computed();
for group in &mut self.groups {
if let Some(activity) = store.get(&group.representative_id) {
group.sport_type = activity.sport_type.clone();
}
if let Some(name) = self.route_names.get(&group.group_id) {
group.custom_name = Some(name.clone());
}
}
self.dirty = false;
}
pub fn groups(&self) -> &[RouteGroup] {
&self.groups
}
pub fn get_group_for_activity(&self, activity_id: &str) -> Option<&RouteGroup> {
self.groups
.iter()
.find(|g| g.activity_ids.contains(&activity_id.to_string()))
}
pub fn get_group(&self, group_id: &str) -> Option<&RouteGroup> {
self.groups.iter().find(|g| g.group_id == group_id)
}
pub fn len(&self) -> usize {
self.groups.len()
}
pub fn is_empty(&self) -> bool {
self.groups.is_empty()
}
pub fn set_route_name(&mut self, route_id: &str, name: &str) {
if name.is_empty() {
self.route_names.remove(route_id);
if let Some(group) = self.groups.iter_mut().find(|g| g.group_id == route_id) {
group.custom_name = None;
}
} else {
self.route_names
.insert(route_id.to_string(), name.to_string());
if let Some(group) = self.groups.iter_mut().find(|g| g.group_id == route_id) {
group.custom_name = Some(name.to_string());
}
}
}
pub fn get_route_name(&self, route_id: &str) -> Option<&String> {
self.route_names.get(route_id)
}
pub fn route_names(&self) -> &HashMap<String, String> {
&self.route_names
}
pub fn set_route_names(&mut self, names: HashMap<String, String>) {
self.route_names = names;
}
}