From 4eda79211e3b7b4e98b86ff7b9a33eeb0701f8c0 Mon Sep 17 00:00:00 2001 From: Jeddunk Date: Sun, 23 Aug 2020 14:58:49 +0200 Subject: [PATCH 1/3] Initial implementation of fuzzy search (fuzzywuzzy library) --- auto-cream-api.iml | 1 + pom.xml | 5 +++++ src/main/java/util/SteamAppsListCache.java | 23 +++++++++++++++------- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/auto-cream-api.iml b/auto-cream-api.iml index f79f6a4..e634122 100644 --- a/auto-cream-api.iml +++ b/auto-cream-api.iml @@ -34,5 +34,6 @@ + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5b15b08..956008e 100644 --- a/pom.xml +++ b/pom.xml @@ -131,5 +131,10 @@ unirest-java 3.1.02 + + me.xdrop + fuzzywuzzy + 1.3.1 + \ No newline at end of file diff --git a/src/main/java/util/SteamAppsListCache.java b/src/main/java/util/SteamAppsListCache.java index eae4bc8..c154519 100644 --- a/src/main/java/util/SteamAppsListCache.java +++ b/src/main/java/util/SteamAppsListCache.java @@ -20,6 +20,8 @@ import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; import kong.unirest.HttpResponse; import kong.unirest.Unirest; +import me.xdrop.fuzzywuzzy.FuzzySearch; +import me.xdrop.fuzzywuzzy.model.BoundExtractedResult; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; @@ -32,10 +34,7 @@ import java.io.*; import java.lang.reflect.Type; import java.time.Duration; import java.time.Instant; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; public class SteamAppsListCache { @@ -94,7 +93,17 @@ public class SteamAppsListCache { } public App findGame(String name) { - for (App app : list.getSteamAppsList()) { + List> match = FuzzySearch.extractTop(name, list.getSteamAppsList(), app -> + app.getName().toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", ""), 25); + System.out.println("\n\n\n==== Top 25 results for \"" + name + "\": ===="); + for (BoundExtractedResult result : match) { + System.out.println(result.getReferent().getName() + " - " + + result.getIndex() + " - " + + result.getScore()); + } + System.out.println("\n\n\n"); + return match.get(0).getReferent(); + /*for (App app : list.getSteamAppsList()) { if (app.getName().toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", "") .startsWith(name.toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", ""))) { return app; @@ -105,8 +114,8 @@ public class SteamAppsListCache { .contains(name.toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", ""))) { return app; } - } - return null; + }*/ + //return null; } private void getListFromApi() { From c2254856da8e1c4b3033a88b9fa7d5b7e6f7f078 Mon Sep 17 00:00:00 2001 From: Jeddunk Date: Mon, 24 Aug 2020 15:27:34 +0200 Subject: [PATCH 2/3] Search function now brings up a window with a list of search results. --- src/main/java/Controller.java | 29 ++++- .../java/SearchResultWindowController.java | 103 ++++++++++++++++++ src/main/java/util/SteamAppsListCache.java | 54 +++++---- src/main/resources/mainWindow.fxml | 84 ++++++++------ src/main/resources/searchResultWindow.fxml | 35 ++++++ 5 files changed, 244 insertions(+), 61 deletions(-) create mode 100644 src/main/java/SearchResultWindowController.java create mode 100644 src/main/resources/searchResultWindow.fxml diff --git a/src/main/java/Controller.java b/src/main/java/Controller.java index 6b7ea6d..0e83eaa 100644 --- a/src/main/java/Controller.java +++ b/src/main/java/Controller.java @@ -19,10 +19,13 @@ import javafx.collections.FXCollections; import javafx.concurrent.Service; import javafx.concurrent.Task; import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Label; import javafx.scene.control.Tooltip; -import javafx.stage.FileChooser; +import javafx.stage.*; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.configuration2.ex.ConfigurationException; import org.jsoup.HttpStatusException; @@ -38,6 +41,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import java.util.List; import java.util.Map; import java.util.Objects; @@ -207,11 +211,28 @@ public class Controller { } public void getAppId() { - final App game = cache.findGame(game_name_textfield.getText()); - if (game == null) { + //final App game = cache.findGame(game_name_textfield.getText()); + final List games = cache.findListOfGames(game_name_textfield.getText()); + if (games.isEmpty()) { appId_textfield.setText("-1"); } else { - appId_textfield.setText(String.valueOf(game.getAppId())); + try { + FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("searchResultWindow.fxml")); + Parent root1 = fxmlLoader.load(); + + SearchResultWindowController c = fxmlLoader.getController(); + c.initMe(games); + c.setParentController(this); + + Stage stage = new Stage(); + stage.initModality(Modality.APPLICATION_MODAL); + //stage.initStyle(StageStyle.UNDECORATED); + stage.setTitle("Choose game..."); + stage.setScene(new Scene(root1)); + stage.show(); + } catch (IOException e) { + e.printStackTrace(); + } } } diff --git a/src/main/java/SearchResultWindowController.java b/src/main/java/SearchResultWindowController.java new file mode 100644 index 0000000..8b4217f --- /dev/null +++ b/src/main/java/SearchResultWindowController.java @@ -0,0 +1,103 @@ +/* + * Auto-CreamAPI + * Copyright (C) 2020 Jeddunk + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see + * . + */ + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; +import javafx.stage.Stage; +import pojo.App; + +import java.util.List; + +public class SearchResultWindowController { + + @FXML + public Button okButton; + @FXML + public Button cancelButton; + @FXML + public TableView gameTable; + @FXML + public TableColumn appIdCol; + @FXML + public TableColumn nameCol; + + public Controller parent; + + private long lastTime; + private boolean isdblClicked; + + public SearchResultWindowController() { + } + + @FXML + public void initialize() { + } + + public void initMe(List games) { + ObservableList data = FXCollections.observableArrayList(games); + try { + appIdCol.setCellValueFactory(new PropertyValueFactory<>("appId")); + nameCol.setCellValueFactory(new PropertyValueFactory<>("name")); + gameTable.setItems(data); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void confirm() { + App app = gameTable.getSelectionModel().getSelectedItem(); + parent.game_name_textfield.setText(app.getName()); + parent.appId_textfield.setText(String.valueOf(app.getAppId())); + Stage current = (Stage) okButton.getScene().getWindow(); + current.close(); + } + + public void cancel() { + parent.game_name_textfield.setText(""); + parent.appId_textfield.setText("-1"); + Stage current = (Stage) cancelButton.getScene().getWindow(); + current.close(); + } + + public void setParentController(Controller controller) { + parent = controller; + } + + public void doubleclickConfirm(MouseEvent mouseEvent) { + if (mouseEvent.getButton() == MouseButton.PRIMARY) { + long diff; + long currentTime = System.currentTimeMillis(); + if (lastTime != 0 && currentTime != 0) { + diff = currentTime - lastTime; + isdblClicked = (diff <= 215); + } + lastTime = currentTime; + if (isdblClicked) { + App app = gameTable.getSelectionModel().getSelectedItem(); + parent.game_name_textfield.setText(app.getName()); + parent.appId_textfield.setText(String.valueOf(app.getAppId())); + Stage current = (Stage) gameTable.getScene().getWindow(); + current.close(); + } + } + } +} diff --git a/src/main/java/util/SteamAppsListCache.java b/src/main/java/util/SteamAppsListCache.java index c154519..41446c2 100644 --- a/src/main/java/util/SteamAppsListCache.java +++ b/src/main/java/util/SteamAppsListCache.java @@ -92,32 +92,38 @@ public class SteamAppsListCache { .filter(app -> app.getName().equalsIgnoreCase(name)).findFirst().orElse(null); } - public App findGame(String name) { - List> match = FuzzySearch.extractTop(name, list.getSteamAppsList(), app -> - app.getName().toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", ""), 25); - System.out.println("\n\n\n==== Top 25 results for \"" + name + "\": ===="); - for (BoundExtractedResult result : match) { - System.out.println(result.getReferent().getName() + " - " + - result.getIndex() + " - " + - result.getScore()); - } - System.out.println("\n\n\n"); - return match.get(0).getReferent(); - /*for (App app : list.getSteamAppsList()) { - if (app.getName().toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", "") - .startsWith(name.toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", ""))) { - return app; - } - } - for (App app : list.getSteamAppsList()) { - if (app.getName().toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", "") - .contains(name.toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", ""))) { - return app; - } - }*/ - //return null; + public List findListOfGames(String name) { + List> match = FuzzySearch.extractSorted(name, list.getSteamAppsList(), app -> + app.getName().toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", ""), 80); + return match.stream().map(BoundExtractedResult::getReferent).collect(Collectors.toList()); } + // public App findGame(String name) { + // List> match = FuzzySearch.extractSorted(name, list.getSteamAppsList(), app -> + // app.getName().toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", ""), 80); + // /*System.out.println("\n\n\n==== Top 25 results for \"" + name + "\": ===="); + // for (BoundExtractedResult result : match) { + // System.out.println(result.getReferent().getName() + " - " + + // result.getIndex() + " - " + + // result.getScore()); + // } + // System.out.println("\n\n\n");*/ + // return match.get(0).getReferent(); + // /*for (App app : list.getSteamAppsList()) { + // if (app.getName().toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", "") + // .startsWith(name.toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", ""))) { + // return app; + // } + // } + // for (App app : list.getSteamAppsList()) { + // if (app.getName().toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", "") + // .contains(name.toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", ""))) { + // return app; + // } + // }*/ + // //return null; + // } + private void getListFromApi() { System.out.println("Trying to get SteamAppList from API..."); List apps = getApps(); diff --git a/src/main/resources/mainWindow.fxml b/src/main/resources/mainWindow.fxml index e4c0317..0c895a3 100644 --- a/src/main/resources/mainWindow.fxml +++ b/src/main/resources/mainWindow.fxml @@ -27,46 +27,64 @@ ~ . --> - + - - - + + + - - - - - - - - - + + + + + + + + + - + - - - - - - - - + + - + - - - - - - - - - - diff --git a/src/main/resources/searchResultWindow.fxml b/src/main/resources/searchResultWindow.fxml new file mode 100644 index 0000000..277fa5f --- /dev/null +++ b/src/main/resources/searchResultWindow.fxml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + +