From a74d26904f04f5c264f1b4ed387c9eff961e8433 Mon Sep 17 00:00:00 2001 From: brianch Date: Wed, 20 Mar 2024 21:00:41 -0300 Subject: [PATCH] Add popularity as a search parameter This is related to the upvotes and downvotes that the puzzle has in lichess. --- settings.json | 1 + src/config.rs | 2 ++ src/db.rs | 6 +++++- src/search_tab.rs | 36 ++++++++++++++++++++++++++++-------- src/settings.rs | 1 + translations/en-US/ocp.ftl | 1 + translations/es/ocp.ftl | 1 + translations/fr/ocp.ftl | 1 + translations/pt-BR/ocp.ftl | 1 + 9 files changed, 41 insertions(+), 9 deletions(-) diff --git a/settings.json b/settings.json index ea0c4aa..8eccc14 100644 --- a/settings.json +++ b/settings.json @@ -16,6 +16,7 @@ "export_pgs": 50, "last_min_rating": 0, "last_max_rating": 1000, + "last_min_popularity": 0, "last_theme": "All", "last_opening": "Any", "last_variation": { diff --git a/src/config.rs b/src/config.rs index a33c6ad..235a8a7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -38,6 +38,7 @@ pub struct OfflinePuzzlesConfig { pub export_pgs: i32, pub last_min_rating: i32, pub last_max_rating: i32, + pub last_min_popularity: i32, pub last_theme: TacticalThemes, pub last_opening: Openings, pub last_variation: Variation, @@ -64,6 +65,7 @@ impl ::std::default::Default for OfflinePuzzlesConfig { export_pgs: 50, last_min_rating: 0, last_max_rating: 1000, + last_min_popularity: 0, last_theme: TacticalThemes::All, last_opening: Openings::Any, last_variation: Variation::ANY, diff --git a/src/db.rs b/src/db.rs index 31f850b..ad98663 100644 --- a/src/db.rs +++ b/src/db.rs @@ -19,7 +19,7 @@ pub fn establish_connection() -> SqliteConnection { .unwrap_or_else(|_| panic!("Error connecting to {}", database_url)) } -pub fn get_favorites(min_rating: i32, max_rating: i32, theme: TacticalThemes, opening: Openings, variation: Variation, op_side: Option, result_limit: usize) -> Option> { +pub fn get_favorites(min_rating: i32, max_rating: i32, min_popularity: i32, theme: TacticalThemes, opening: Openings, variation: Variation, op_side: Option, result_limit: usize) -> Option> { let mut conn = establish_connection(); let results; let theme_filter = String::from("%") + theme.get_tag_name() + "%"; @@ -27,6 +27,7 @@ pub fn get_favorites(min_rating: i32, max_rating: i32, theme: TacticalThemes, op if opening == Openings::Any { results = favs .filter(rating.between(min_rating, max_rating)) + .filter(popularity.ge(min_popularity)) .filter(themes.like(theme_filter)) .limit(limit) .load::(&mut conn); @@ -44,6 +45,7 @@ pub fn get_favorites(min_rating: i32, max_rating: i32, theme: TacticalThemes, op if side == OpeningSide::White { results = favs .filter(rating.between(min_rating, max_rating)) + .filter(popularity.ge(min_popularity)) .filter(themes.like(theme_filter)) .filter(opening_filter) .filter(game_url.like("%black%")) @@ -52,6 +54,7 @@ pub fn get_favorites(min_rating: i32, max_rating: i32, theme: TacticalThemes, op } else if side == OpeningSide::Black { results = favs .filter(rating.between(min_rating, max_rating)) + .filter(popularity.ge(min_popularity)) .filter(themes.like(theme_filter)) .filter(opening_filter) .filter(game_url.not_like("%black%")) @@ -60,6 +63,7 @@ pub fn get_favorites(min_rating: i32, max_rating: i32, theme: TacticalThemes, op } else { results = favs .filter(rating.between(min_rating, max_rating)) + .filter(popularity.ge(min_popularity)) .filter(themes.like(theme_filter)) .filter(opening_filter) .limit(limit) diff --git a/src/search_tab.rs b/src/search_tab.rs index b592202..19115b9 100644 --- a/src/search_tab.rs +++ b/src/search_tab.rs @@ -17,6 +17,7 @@ use openings::{Openings, Variation}; pub enum SearchMesssage { SliderMinRatingChanged(i32), SliderMaxRatingChanged(i32), + SliderMinPopularityChanged(i32), SelectTheme(PickListWrapper), SelectOpening(PickListWrapper), SelectVariation(PickListWrapper), @@ -207,6 +208,7 @@ pub struct SearchTab { pub opening_side: Option, slider_min_rating_value: i32, slider_max_rating_value: i32, + slider_min_popularity: i32, pub piece_theme_promotion: styles::PieceTheme, pub piece_to_promote_to: Piece, @@ -225,6 +227,7 @@ impl SearchTab { opening_side: config::SETTINGS.last_opening_side, slider_min_rating_value: config::SETTINGS.last_min_rating, slider_max_rating_value: config::SETTINGS.last_max_rating, + slider_min_popularity: config::SETTINGS.last_min_popularity, piece_theme_promotion: config::SETTINGS.piece_theme, piece_to_promote_to: Piece::Queen, show_searching_msg: false, @@ -242,6 +245,9 @@ impl SearchTab { } SearchMesssage::SliderMaxRatingChanged(new_value) => { self.slider_max_rating_value = new_value; Command::none() + } SearchMesssage::SliderMinPopularityChanged(new_value) => { + self.slider_min_popularity = new_value; + Command::none() } SearchMesssage::SelectTheme(new_theme) => { self.theme = new_theme; Command::none() @@ -261,20 +267,20 @@ impl SearchTab { } SearchMesssage::ClickSearch => { self.show_searching_msg = true; SearchTab::save_search_settings(self.slider_min_rating_value, - self.slider_max_rating_value, self.theme.item, + self.slider_max_rating_value, self.slider_min_popularity, self.theme.item, self.opening.item, self.variation.item.clone(), self.opening_side); let config = load_config(); if self.base == Some(SearchBase::Favorites) { Command::perform( SearchTab::search_favs(self.slider_min_rating_value, - self.slider_max_rating_value, + self.slider_max_rating_value, self.slider_min_popularity, self.theme.item, self.opening.item, self.variation.item.clone(), self.opening_side, config.search_results_limit), Message::LoadPuzzle) } else { Command::perform( SearchTab::search(self.slider_min_rating_value, - self.slider_max_rating_value, + self.slider_max_rating_value, self.slider_min_popularity, self.theme.item, self.opening.item, self.variation.item.clone(), self.opening_side, config.search_results_limit), Message::LoadPuzzle) } @@ -285,13 +291,14 @@ impl SearchTab { } } - pub fn save_search_settings(min_rating: i32, max_rating: i32, theme: TacticalThemes, opening: Openings, variation: Variation, op_side: Option) { + pub fn save_search_settings(min_rating: i32, max_rating: i32, min_popularity: i32, theme: TacticalThemes, opening: Openings, variation: Variation, op_side: Option) { let file = std::fs::File::open("settings.json"); if let Ok(file) = file { let buf_reader = BufReader::new(file); if let Ok(mut config) = serde_json::from_reader::, config::OfflinePuzzlesConfig>(buf_reader) { config.last_min_rating = min_rating; config.last_max_rating = max_rating; + config.last_min_popularity = min_popularity; config.last_theme = theme; config.last_opening = opening; config.last_variation = variation; @@ -307,11 +314,11 @@ impl SearchTab { } } - pub async fn search_favs(min_rating: i32, max_rating: i32, theme: TacticalThemes, opening: Openings, variation:Variation, op_side: Option, result_limit: usize) -> Option> { - db::get_favorites(min_rating, max_rating, theme, opening, variation, op_side, result_limit) + pub async fn search_favs(min_rating: i32, max_rating: i32, min_popularity: i32, theme: TacticalThemes, opening: Openings, variation:Variation, op_side: Option, result_limit: usize) -> Option> { + db::get_favorites(min_rating, max_rating, min_popularity, theme, opening, variation, op_side, result_limit) } - pub async fn search(min_rating: i32, max_rating: i32, theme: TacticalThemes, opening: Openings, variation: Variation, op_side: Option, result_limit: usize) -> Option> { + pub async fn search(min_rating: i32, max_rating: i32, min_popularity: i32, theme: TacticalThemes, opening: Openings, variation: Variation, op_side: Option, result_limit: usize) -> Option> { let mut puzzles: Vec = Vec::new(); let reader = csv::ReaderBuilder::new() @@ -339,6 +346,7 @@ impl SearchTab { if let Ok(record) = result { if record.opening.contains(opening_tag) && record.rating >= min_rating && record.rating <= max_rating && + record.popularity >= min_popularity && record.themes.contains(theme.get_tag_name()) { puzzles.push(record); } @@ -353,6 +361,7 @@ impl SearchTab { if record.opening.contains(opening_tag) && !record.game_url.contains("black") && record.rating >= min_rating && record.rating <= max_rating && + record.popularity >= min_popularity && record.themes.contains(theme.get_tag_name()) { puzzles.push(record); } @@ -367,6 +376,7 @@ impl SearchTab { if record.opening.contains(opening_tag) && record.game_url.contains("black") && record.rating >= min_rating && record.rating <= max_rating && + record.popularity >= min_popularity && record.themes.contains(theme.get_tag_name()) { puzzles.push(record); } @@ -381,6 +391,7 @@ impl SearchTab { for result in reader.deserialize::() { if let Ok(record) = result { if record.rating >= min_rating && record.rating <= max_rating && + record.popularity >= min_popularity && record.themes.contains(theme.get_tag_name()) { puzzles.push(record); } @@ -433,6 +444,15 @@ impl Tab for SearchTab { ), Text::new(self.slider_max_rating_value.to_string()) ].width(Length::Fill), + row![ + Text::new(lang::tr(&self.lang, "min_popularity")), + Slider::new( + -100..=100, + self.slider_min_popularity, + SearchMesssage::SliderMinPopularityChanged, + ), + Text::new(self.slider_min_popularity.to_string()) + ].width(Length::Fill), Text::new(lang::tr(&self.lang, "theme_label")), PickList::new( PickListWrapper::get_themes(self.lang), @@ -450,7 +470,7 @@ impl Tab for SearchTab { PickListWrapper::get_variations(self.lang, Some(&self.opening.item)), Some(self.variation.clone()), SearchMesssage::SelectVariation - ) + ), ].padding([0, 0, 30, 0]).spacing(10).align_items(Alignment::Center); if self.opening.item != Openings::Any { diff --git a/src/settings.rs b/src/settings.rs index b6b2ff8..1747311 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -152,6 +152,7 @@ impl SettingsTab { export_pgs: self.export_pgs.parse().unwrap(), last_min_rating: self.saved_configs.last_min_rating, last_max_rating: self.saved_configs.last_max_rating, + last_min_popularity: self.saved_configs.last_min_popularity, last_theme: self.saved_configs.last_theme, last_opening: self.saved_configs.last_opening, last_variation: self.saved_configs.last_variation.clone(), diff --git a/translations/en-US/ocp.ftl b/translations/en-US/ocp.ftl index 0466f17..b23325b 100644 --- a/translations/en-US/ocp.ftl +++ b/translations/en-US/ocp.ftl @@ -40,6 +40,7 @@ lichess_db = Lichess DB my_favories = My Favorites min_rating = Min. Rating:{" "} max_rating = Max. Rating:{" "} +min_popularity = Popularity (-100 to 100):{" "} theme_label = Tactics theme: in_opening = In the opening: in_the_variation = Variation: diff --git a/translations/es/ocp.ftl b/translations/es/ocp.ftl index 5ddeadd..b639d73 100644 --- a/translations/es/ocp.ftl +++ b/translations/es/ocp.ftl @@ -40,6 +40,7 @@ lichess_db = Base de datos de Lichess my_favories = Mis favoritos min_rating = Rating Min.:{" "} max_rating = Rating Max.:{" "} +min_popularity = Popularidad (de -100 a 100):{" "} theme_label = Tema táctico: in_opening = En la apertura: in_the_variation = Variante: diff --git a/translations/fr/ocp.ftl b/translations/fr/ocp.ftl index 5a42805..34c0181 100644 --- a/translations/fr/ocp.ftl +++ b/translations/fr/ocp.ftl @@ -42,6 +42,7 @@ lichess_db = BdD Lichess my_favories = Mes favoris min_rating = Classement minimal:{" "} max_rating = Classement maximal:{" "} +min_popularity = Popularity (-100 to 100):{" "} theme_label = Thème tactique: in_opening = Issu de l'ouverture: in_the_variation = Avec la variante: diff --git a/translations/pt-BR/ocp.ftl b/translations/pt-BR/ocp.ftl index d272b28..c629ab4 100644 --- a/translations/pt-BR/ocp.ftl +++ b/translations/pt-BR/ocp.ftl @@ -40,6 +40,7 @@ lichess_db = Banco de Dados do Lichess my_favories = Meus Favoritos min_rating = Rating Min.:{" "} max_rating = Rating Máx.:{" "} +min_popularity = Popularidade (de -100 a 100):{" "} theme_label = Tema Tático: in_opening = Na Abertura: in_the_variation = Variante: