mirror of
https://github.com/ow-mods/ow-mod-man.git
synced 2025-12-11 20:15:50 +01:00
[CORE] More search fields for local search, tie breaking
This commit is contained in:
parent
2f520ebb6b
commit
890890aa48
@ -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<LocalModWithRemoteName> = mods
|
||||
let mods: Vec<LocalModWithRemoteSearchData> = 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();
|
||||
|
||||
@ -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<String>,
|
||||
remote: Option<RemoteMod>,
|
||||
}
|
||||
|
||||
impl<'a> LocalModWithRemoteName<'a> {
|
||||
pub fn new(local_mod: &'a UnsafeLocalMod, remote_name: Option<String>) -> Self {
|
||||
Self {
|
||||
local_mod,
|
||||
remote_name,
|
||||
}
|
||||
impl<'a> LocalModWithRemoteSearchData<'a> {
|
||||
pub fn new(local_mod: &'a UnsafeLocalMod, remote: Option<RemoteMod>) -> Self {
|
||||
Self { local_mod, remote }
|
||||
}
|
||||
}
|
||||
|
||||
impl Searchable for LocalModWithRemoteName<'_> {
|
||||
impl Searchable for LocalModWithRemoteSearchData<'_> {
|
||||
fn get_values(&self) -> Vec<String> {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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<String>;
|
||||
|
||||
/// 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)]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user