diff --git a/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/activity/GameCollectionActivity.java b/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/activity/GameCollectionActivity.java index f079ce8c..1c03e576 100644 --- a/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/activity/GameCollectionActivity.java +++ b/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/activity/GameCollectionActivity.java @@ -14,13 +14,11 @@ import com.playshogi.website.gwt.client.place.GameCollectionPlace; import com.playshogi.website.gwt.client.ui.GameCollectionView; import com.playshogi.website.gwt.shared.models.GameCollectionDetailsAndGames; -import com.playshogi.website.gwt.shared.models.GameDetails; +import com.playshogi.website.gwt.shared.models.KifuSearchFilterDetails; import com.playshogi.website.gwt.shared.services.KifuService; import com.playshogi.website.gwt.shared.services.KifuServiceAsync; import org.dominokit.domino.ui.notifications.Notification; -import java.util.Arrays; - public class GameCollectionActivity extends MyAbstractActivity { private final KifuServiceAsync kifuService = GWT.create(KifuService.class); @@ -143,9 +141,29 @@ public void onSuccess(final Void unused) { public void onSearchKifus(final SearchKifusEvent event) { GWT.log("GameCollectionActivity Handling SearchKifusEvent"); - eventBus.fireEvent(new ListCollectionGamesEvent( - Arrays.stream(games.getGames()).filter(x -> event.getPlayer().equals(x.getSente())).toArray(GameDetails[]::new), - games.getDetails())); + + KifuSearchFilterDetails filterDetails = new KifuSearchFilterDetails(); + filterDetails.setPartialPositionSearchSfen(event.getPartialPositionSfen()); + if (event.getResult() != null) filterDetails.setGameResult(event.getResult().name()); + filterDetails.setPlayerName(event.getPlayer()); + + GWT.log("Querying for collection games with filter"); + kifuService.getGameSetKifuDetailsWithFilter(sessionInformation.getSessionId(), place.getCollectionId(), + filterDetails, + + new AsyncCallback() { + @Override + public void onFailure(Throwable throwable) { + GWT.log("GameCollectionActivity: error retrieving collection games with filter"); + } + + @Override + public void onSuccess(GameCollectionDetailsAndGames result) { + games = result; + GWT.log("GameCollectionActivity: retrieved collection games with filter: " + result.getGames().length); + eventBus.fireEvent(new ListCollectionGamesEvent(result.getGames(), result.getDetails())); + } + }); } private void refresh() { diff --git a/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/events/collections/SearchKifusEvent.java b/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/events/collections/SearchKifusEvent.java index 6a47dd47..c7c0b3e5 100644 --- a/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/events/collections/SearchKifusEvent.java +++ b/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/events/collections/SearchKifusEvent.java @@ -5,12 +5,13 @@ public class SearchKifusEvent extends GenericEvent { private final GameResult result; - private final String player; + private final String partialPositionSfen; - public SearchKifusEvent(final GameResult result, String player) { + public SearchKifusEvent(final GameResult result, String player, String partialPositionSfen) { this.result = result; this.player = player; + this.partialPositionSfen = partialPositionSfen; } public GameResult getResult() { @@ -20,4 +21,8 @@ public GameResult getResult() { public String getPlayer() { return player; } + + public String getPartialPositionSfen() { + return partialPositionSfen; + } } diff --git a/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/widget/collections/SearchKifuForm.java b/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/widget/collections/SearchKifuForm.java index ddb83aba..2d7f8cac 100644 --- a/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/widget/collections/SearchKifuForm.java +++ b/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/widget/collections/SearchKifuForm.java @@ -21,12 +21,15 @@ public class SearchKifuForm { private Select gameResult; private SuggestBox playerName; private EventBus eventBus; + private TextBox partialSearch; public HtmlContentBuilder getForm() { if (div != null) { return div; } + partialSearch = TextBox.create().setLabel("Search for partial position").setHelperText("SFEN"); + playerName = SuggestBox.create("Player:", playerNames) .setHelperText("Type any letter and see suggestions"); @@ -39,7 +42,7 @@ public HtmlContentBuilder getForm() { .setSearchable(false) .selectAt(0); - div = Elements.div().add(playerName).add(gameResult); + div = Elements.div().add(partialSearch).add(playerName).add(gameResult); return div; } @@ -59,7 +62,8 @@ public void showInPopup() { closeButton.addClickListener(evt -> modal.close()); Button searchButton = Button.create("SEARCH").linkify(); searchButton.addClickListener(evt -> { - eventBus.fireEvent(new SearchKifusEvent(gameResult.getValue(), playerName.getValue())); + eventBus.fireEvent(new SearchKifusEvent(gameResult.getValue(), playerName.getValue(), + partialSearch.getValue())); modal.close(); }); modal.appendFooterChild(searchButton); diff --git a/playshogi-website/playshogi-website-server/src/main/java/com/playshogi/website/gwt/server/services/KifuServiceImpl.java b/playshogi-website/playshogi-website-server/src/main/java/com/playshogi/website/gwt/server/services/KifuServiceImpl.java index f62eacac..bef55243 100644 --- a/playshogi-website/playshogi-website-server/src/main/java/com/playshogi/website/gwt/server/services/KifuServiceImpl.java +++ b/playshogi-website/playshogi-website-server/src/main/java/com/playshogi/website/gwt/server/services/KifuServiceImpl.java @@ -5,6 +5,9 @@ import com.playshogi.library.database.*; import com.playshogi.library.database.models.*; import com.playshogi.library.database.models.PersistentKifu.KifuType; +import com.playshogi.library.database.search.KifuSearchFilter; +import com.playshogi.library.database.search.KifuSearchManager; +import com.playshogi.library.database.search.KifuSearchResult; import com.playshogi.library.shogi.engine.*; import com.playshogi.library.shogi.engine.insights.GameInsights; import com.playshogi.library.shogi.engine.insights.Mistake; @@ -44,6 +47,8 @@ public class KifuServiceImpl extends RemoteServiceServlet implements KifuService private final TsumeEscapeSolver tsumeEscapeSolver = new TsumeEscapeSolver(queuedTsumeSolver); private final QueuedKifuAnalyzer queuedKifuAnalyzer = new QueuedKifuAnalyzer(EngineConfiguration.NORMAL_ENGINE); + private final KifuSearchManager kifuSearchManager = new KifuSearchManager(); + public KifuServiceImpl() { DbConnection dbConnection = new DbConnection(); gameSetRepository = new GameSetRepository(dbConnection); @@ -227,6 +232,49 @@ public GameCollectionDetailsAndGames getGameSetKifuDetails(final String sessionI return result; } + @Override + public GameCollectionDetailsAndGames getGameSetKifuDetailsWithFilter(final String sessionId, + final String gameSetId, + final KifuSearchFilterDetails filterDetails) { + LOGGER.log(Level.INFO, "getGameSetKifuDetailsWithFilter:\n" + gameSetId + "\n" + filterDetails); + + //TODO access control + + LoginResult loginResult = authenticator.checkSession(sessionId); + if (loginResult == null || !loginResult.isLoggedIn() || loginResult.getUserId() != 2) { + throw new IllegalStateException("Only some logged in users can search for games"); + } + + PersistentGameSet gameSet = gameSetRepository.getGameSetById(Integer.parseInt(gameSetId)); + if (gameSet == null) { + throw new IllegalArgumentException("Invalid gameSet ID"); + } + + List games = gameRepository.getGamesFromGameSet(Integer.parseInt(gameSetId)); + + List kifuSearchResults = kifuSearchManager.searchGames(createKifuSearchFilter(filterDetails)); + + + GameCollectionDetailsAndGames result = new GameCollectionDetailsAndGames(); + result.setDetails(getCollectionDetails(gameSet)); + result.setGames(games.stream().filter(g -> matchesFilter(filterDetails, kifuSearchResults, g)) + .map(this::createGameDetails).toArray(GameDetails[]::new)); + + return result; + } + + private boolean matchesFilter(final KifuSearchFilterDetails filterDetails, + final List kifuSearchResults, PersistentGame game) { + String playerName = filterDetails.getPlayerName(); + if (!Strings.isNullOrEmpty(playerName) && !game.getSenteName().startsWith(playerName) && !game.getSenteName().startsWith(playerName)) + return false; + return kifuSearchResults.stream().anyMatch(r -> r.getKifu().getId() == game.getKifuId()); + } + + private KifuSearchFilter createKifuSearchFilter(final KifuSearchFilterDetails filterDetails) { + return new KifuSearchFilter(SfenConverter.fromSFEN(filterDetails.getPartialPositionSearchSfen())); + } + private GameDetails createGameDetails(final PersistentGame game) { GameDetails gameDetails = new GameDetails(); gameDetails.setId(String.valueOf(game.getId())); diff --git a/playshogi-website/playshogi-website-shared/src/main/java/com/playshogi/website/gwt/shared/models/KifuSearchFilterDetails.java b/playshogi-website/playshogi-website-shared/src/main/java/com/playshogi/website/gwt/shared/models/KifuSearchFilterDetails.java new file mode 100644 index 00000000..9377ec80 --- /dev/null +++ b/playshogi-website/playshogi-website-shared/src/main/java/com/playshogi/website/gwt/shared/models/KifuSearchFilterDetails.java @@ -0,0 +1,46 @@ +package com.playshogi.website.gwt.shared.models; + +import java.io.Serializable; + +public class KifuSearchFilterDetails implements Serializable { + + private String partialPositionSearchSfen; + private String playerName; + private String gameResult; + + public KifuSearchFilterDetails() { + } + + public String getPartialPositionSearchSfen() { + return partialPositionSearchSfen; + } + + public void setPartialPositionSearchSfen(final String partialPositionSearchSfen) { + this.partialPositionSearchSfen = partialPositionSearchSfen; + } + + public String getPlayerName() { + return playerName; + } + + public void setPlayerName(final String playerName) { + this.playerName = playerName; + } + + public String getGameResult() { + return gameResult; + } + + public void setGameResult(final String gameResult) { + this.gameResult = gameResult; + } + + @Override + public String toString() { + return "KifuSearchFilterDetails{" + + "partialPositionSearchSfen='" + partialPositionSearchSfen + '\'' + + ", playerName='" + playerName + '\'' + + ", gameResult='" + gameResult + '\'' + + '}'; + } +} diff --git a/playshogi-website/playshogi-website-shared/src/main/java/com/playshogi/website/gwt/shared/services/KifuService.java b/playshogi-website/playshogi-website-shared/src/main/java/com/playshogi/website/gwt/shared/services/KifuService.java index c39db613..690eca32 100644 --- a/playshogi-website/playshogi-website-shared/src/main/java/com/playshogi/website/gwt/shared/services/KifuService.java +++ b/playshogi-website/playshogi-website-shared/src/main/java/com/playshogi/website/gwt/shared/services/KifuService.java @@ -15,6 +15,9 @@ public interface KifuService extends RemoteService { GameCollectionDetailsAndGames getGameSetKifuDetails(String sessionId, String gameSetId); + GameCollectionDetailsAndGames getGameSetKifuDetailsWithFilter(String sessionId, String gameSetId, + KifuSearchFilterDetails filterDetails); + PositionDetails getPositionDetails(String sfen, String gameSetId); PositionEvaluationDetails analysePosition(String sessionId, String sfen); diff --git a/playshogi-website/playshogi-website-shared/src/main/java/com/playshogi/website/gwt/shared/services/KifuServiceAsync.java b/playshogi-website/playshogi-website-shared/src/main/java/com/playshogi/website/gwt/shared/services/KifuServiceAsync.java index 355da4b5..014293a0 100644 --- a/playshogi-website/playshogi-website-shared/src/main/java/com/playshogi/website/gwt/shared/services/KifuServiceAsync.java +++ b/playshogi-website/playshogi-website-shared/src/main/java/com/playshogi/website/gwt/shared/services/KifuServiceAsync.java @@ -16,6 +16,9 @@ void saveGameAndAddToCollection(String sessionId, String kifuUsf, String collect void getGameSetKifuDetails(String sessionId, String gameSetId, AsyncCallback callback); + void getGameSetKifuDetailsWithFilter(String sessionId, String gameSetId, KifuSearchFilterDetails filterDetails, + AsyncCallback callback); + void getPositionDetails(String sfen, String gameSetId, AsyncCallback callback); void analysePosition(String sessionId, String sfen, AsyncCallback callback);