From 890890aa4844975f58685f3413e58fceaa260697 Mon Sep 17 00:00:00 2001 From: Ben C Date: Wed, 7 Aug 2024 21:02:09 -0400 Subject: [PATCH] [CORE] More search fields for local search, tie breaking --- owmods_core/src/db/local.rs | 10 ++++------ owmods_core/src/db/mod.rs | 28 +++++++++++++++++----------- owmods_core/src/mods/remote.rs | 4 ++++ owmods_core/src/search.rs | 9 ++++++++- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/owmods_core/src/db/local.rs b/owmods_core/src/db/local.rs index 0d020b55..edccac61 100644 --- a/owmods_core/src/db/local.rs +++ b/owmods_core/src/db/local.rs @@ -15,7 +15,7 @@ use crate::{ validate::{check_mod, ModValidationError}, }; -use super::combined_search::LocalModWithRemoteName; +use super::combined_search::LocalModWithRemoteSearchData; use super::{fix_version, RemoteDatabase}; /// Represents the local (on the local PC) database of mods. @@ -329,13 +329,11 @@ impl LocalDatabase { remote_db: &RemoteDatabase, ) -> Vec<&UnsafeLocalMod> { let mods: Vec<&UnsafeLocalMod> = self.all().collect(); - let mods: Vec = mods + let mods: Vec = mods .into_iter() .map(|m| { - let remote_name = remote_db - .get_mod(m.get_unique_name()) - .map(|m| m.name.clone()); - LocalModWithRemoteName::new(m, remote_name) + let remote = remote_db.get_mod(m.get_unique_name()).cloned(); + LocalModWithRemoteSearchData::new(m, remote) }) .collect(); let mods = mods.iter().collect(); diff --git a/owmods_core/src/db/mod.rs b/owmods_core/src/db/mod.rs index 3c84ac63..4c0ab3d2 100644 --- a/owmods_core/src/db/mod.rs +++ b/owmods_core/src/db/mod.rs @@ -13,34 +13,40 @@ fn fix_version(version: &str) -> &str { mod combined_search { use crate::mods::local::UnsafeLocalMod; + use crate::mods::remote::RemoteMod; use crate::search::Searchable; - pub struct LocalModWithRemoteName<'a> { + pub struct LocalModWithRemoteSearchData<'a> { pub local_mod: &'a UnsafeLocalMod, - remote_name: Option, + remote: Option, } - impl<'a> LocalModWithRemoteName<'a> { - pub fn new(local_mod: &'a UnsafeLocalMod, remote_name: Option) -> Self { - Self { - local_mod, - remote_name, - } + impl<'a> LocalModWithRemoteSearchData<'a> { + pub fn new(local_mod: &'a UnsafeLocalMod, remote: Option) -> Self { + Self { local_mod, remote } } } - impl Searchable for LocalModWithRemoteName<'_> { + impl Searchable for LocalModWithRemoteSearchData<'_> { fn get_values(&self) -> Vec { - if let Some(name) = &self.remote_name { + if let Some(ref remote) = self.remote { self.local_mod .get_values() .into_iter() - .chain(vec![name.clone()]) + .chain(remote.get_values()) .collect() } else { self.local_mod.get_values() } } + + fn break_tie(&self, other: &Self) -> std::cmp::Ordering { + if let (Some(self_remote), Some(other_remote)) = (&self.remote, &other.remote) { + self_remote.break_tie(other_remote) + } else { + self.remote.is_some().cmp(&other.remote.is_some()).reverse() + } + } } } diff --git a/owmods_core/src/mods/remote.rs b/owmods_core/src/mods/remote.rs index 3746f42e..51c4331b 100644 --- a/owmods_core/src/mods/remote.rs +++ b/owmods_core/src/mods/remote.rs @@ -77,6 +77,10 @@ impl Searchable for RemoteMod { self.description.clone(), ] } + + fn break_tie(&self, other: &Self) -> std::cmp::Ordering { + self.download_count.cmp(&other.download_count).reverse() + } } /// A prerelease for a mod diff --git a/owmods_core/src/search.rs b/owmods_core/src/search.rs index 605a3818..05724761 100644 --- a/owmods_core/src/search.rs +++ b/owmods_core/src/search.rs @@ -1,3 +1,5 @@ +use std::cmp::Ordering; + use unicode_normalization::UnicodeNormalization; /// Represents an object that can be searched @@ -6,6 +8,11 @@ pub trait Searchable { /// Each value will be weighted based on its position in the list (first is most important) /// Values are automatically normalized for optimal searching via [normalize_value] when using [search_list] fn get_values(&self) -> Vec; + + /// In the event two items have the same score, this function will be called to break the tie + fn break_tie(&self, _other: &Self) -> Ordering { + Ordering::Equal + } } /// Normalizes a string for optimal searching @@ -88,7 +95,7 @@ where } }) .collect(); - scores.sort_by(|(_, a), (_, b)| a.total_cmp(b).reverse()); + scores.sort_by(|(s, a), (o, b)| a.total_cmp(b).reverse().then_with(|| s.break_tie(o))); scores.iter().map(|(m, _)| *m).collect() } #[cfg(test)]