diff --git a/playshogi-library-database/src/main/java/com/playshogi/library/database/GameRepository.java b/playshogi-library-database/src/main/java/com/playshogi/library/database/GameRepository.java index 3eeb92d7..2ed97ff5 100644 --- a/playshogi-library-database/src/main/java/com/playshogi/library/database/GameRepository.java +++ b/playshogi-library-database/src/main/java/com/playshogi/library/database/GameRepository.java @@ -100,13 +100,18 @@ public PersistentGame getGameById(final int gameId) { } public List getGamesFromGameSet(final int gameSetId) { + return getGamesFromGameSet(gameSetId, false); + } + + public List getGamesFromGameSet(final int gameSetId, final boolean reducedLogging) { ArrayList games = new ArrayList<>(); Connection connection = dbConnection.getConnection(); try (PreparedStatement preparedStatement = connection.prepareStatement(SELECT_GAMES_FROM_GAMESET)) { preparedStatement.setInt(1, gameSetId); ResultSet rs = preparedStatement.executeQuery(); while (rs.next()) { - LOGGER.log(Level.INFO, "Found game with id: " + rs.getInt("game_id")); + if (!reducedLogging) + LOGGER.log(Level.INFO, "Found game with id: " + rs.getInt("game_id")); int kifuId = rs.getInt("kifu_id"); int gameId = rs.getInt("game_id"); diff --git a/playshogi-library-database/src/main/java/com/playshogi/library/database/KifuRepository.java b/playshogi-library-database/src/main/java/com/playshogi/library/database/KifuRepository.java index 10f2fcca..726f7b8e 100644 --- a/playshogi-library-database/src/main/java/com/playshogi/library/database/KifuRepository.java +++ b/playshogi-library-database/src/main/java/com/playshogi/library/database/KifuRepository.java @@ -77,12 +77,17 @@ public int saveKifu(final GameRecord gameRecord, final String name, final int au } public PersistentKifu getKifuById(final int kifuId) { + return getKifuById(kifuId, false); + } + + public PersistentKifu getKifuById(final int kifuId, final boolean reducedLogging) { Connection connection = dbConnection.getConnection(); try (PreparedStatement preparedStatement = connection.prepareStatement(SELECT_KIFU)) { preparedStatement.setInt(1, kifuId); ResultSet rs = preparedStatement.executeQuery(); if (rs.next()) { - LOGGER.log(Level.INFO, "Found kifu: " + rs.getString("name") + " with id: " + rs.getInt("id")); + if (!reducedLogging) + LOGGER.log(Level.INFO, "Found kifu: " + rs.getString("name") + " with id: " + rs.getInt("id")); String name = rs.getString("name"); int authorId = rs.getInt("author_id"); String usfString = rs.getString("usf"); diff --git a/playshogi-library-database/src/main/java/com/playshogi/library/database/search/KifuSearchFilter.java b/playshogi-library-database/src/main/java/com/playshogi/library/database/search/KifuSearchFilter.java new file mode 100644 index 00000000..c5af4d27 --- /dev/null +++ b/playshogi-library-database/src/main/java/com/playshogi/library/database/search/KifuSearchFilter.java @@ -0,0 +1,16 @@ +package com.playshogi.library.database.search; + +import com.playshogi.library.shogi.models.position.ReadOnlyShogiPosition; + +public class KifuSearchFilter { + + private final ReadOnlyShogiPosition partialPositionSearch; + + public KifuSearchFilter(final ReadOnlyShogiPosition partialPositionSearch) { + this.partialPositionSearch = partialPositionSearch; + } + + public ReadOnlyShogiPosition getPartialPositionSearch() { + return partialPositionSearch; + } +} diff --git a/playshogi-library-database/src/main/java/com/playshogi/library/database/search/KifuSearchManager.java b/playshogi-library-database/src/main/java/com/playshogi/library/database/search/KifuSearchManager.java new file mode 100644 index 00000000..b45d1582 --- /dev/null +++ b/playshogi-library-database/src/main/java/com/playshogi/library/database/search/KifuSearchManager.java @@ -0,0 +1,78 @@ +package com.playshogi.library.database.search; + +import com.playshogi.library.database.DbConnection; +import com.playshogi.library.database.GameRepository; +import com.playshogi.library.database.KifuRepository; +import com.playshogi.library.database.models.PersistentGame; +import com.playshogi.library.database.models.PersistentKifu; +import com.playshogi.library.shogi.models.formats.sfen.SfenConverter; +import com.playshogi.library.shogi.models.position.ReadOnlyShogiPosition; +import com.playshogi.library.shogi.models.position.Square; +import com.playshogi.library.shogi.models.record.GameNavigation; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class KifuSearchManager { + + private static final Logger LOGGER = Logger.getLogger(KifuSearchManager.class.getName()); + + + private final GameRepository gameRepository = new GameRepository(new DbConnection()); + private final KifuRepository kifuRepository = new KifuRepository(new DbConnection()); + + private final List kifus = new ArrayList<>(); + + public KifuSearchManager() { + System.out.println("Loading games from db..."); + List games = gameRepository.getGamesFromGameSet(1, true); + for (PersistentGame game : games) { + if (game.getKifuId() % 1000 == 0) System.out.println("Loading #" + game.getKifuId()); + try { + kifus.add(kifuRepository.getKifuById(game.getKifuId(), true)); + } catch (Exception ex) { + LOGGER.log(Level.SEVERE, "Error loading the kifu " + game.getKifuId(), ex); + } + } + System.out.println("Loaded games from db!"); + } + + public List searchGames(final KifuSearchFilter filter) { + List result = new ArrayList<>(); + for (PersistentKifu persistentKifu : kifus) { + GameNavigation navigation = new GameNavigation(persistentKifu.getKifu().getGameTree()); + int movec = 0; + while (navigation.canMoveForward() && movec++ < 40) { + navigation.moveForward(); + if (positionContains(navigation.getPosition(), filter.getPartialPositionSearch())) { + System.out.println(persistentKifu.getKifu().getGameInformation() + " - In kifu #" + persistentKifu.getId() + ":"); + System.out.println(navigation.getPosition()); + + result.add(new KifuSearchResult(persistentKifu, navigation.getPosition())); + break; + } + } + } + + return result; + } + + private boolean positionContains(final ReadOnlyShogiPosition fullPosition, + final ReadOnlyShogiPosition partialPosition) { + for (Square square : partialPosition.getAllSquares()) { + if (partialPosition.isEmptySquare(square)) continue; + if (fullPosition.isEmptySquare(square)) return false; + if (partialPosition.getPieceAt(square).get() != fullPosition.getPieceAt(square).get()) return false; + } + + //TODO komadai? + return true; + } + + public static void main(String[] args) { + KifuSearchManager manager = new KifuSearchManager(); + manager.searchGames(new KifuSearchFilter(SfenConverter.fromSFEN("9/9/9/9/9/9/9/6R2/9 b kr2b4g4s4n4l18p"))); + } +} diff --git a/playshogi-library-database/src/main/java/com/playshogi/library/database/search/KifuSearchResult.java b/playshogi-library-database/src/main/java/com/playshogi/library/database/search/KifuSearchResult.java new file mode 100644 index 00000000..d4f729e8 --- /dev/null +++ b/playshogi-library-database/src/main/java/com/playshogi/library/database/search/KifuSearchResult.java @@ -0,0 +1,22 @@ +package com.playshogi.library.database.search; + +import com.playshogi.library.database.models.PersistentKifu; +import com.playshogi.library.shogi.models.position.ReadOnlyShogiPosition; + +public class KifuSearchResult { + private final PersistentKifu kifu; + private final ReadOnlyShogiPosition position; + + public KifuSearchResult(final PersistentKifu kifu, final ReadOnlyShogiPosition position) { + this.kifu = kifu; + this.position = position; + } + + public PersistentKifu getKifu() { + return kifu; + } + + public ReadOnlyShogiPosition getPosition() { + return position; + } +} diff --git a/playshogi-library-database/src/test/java/com/playshogi/library/database/GameSetRepositoryTest.java b/playshogi-library-database/src/test/java/com/playshogi/library/database/GameSetRepositoryTest.java index 38e9354a..2c8799be 100644 --- a/playshogi-library-database/src/test/java/com/playshogi/library/database/GameSetRepositoryTest.java +++ b/playshogi-library-database/src/test/java/com/playshogi/library/database/GameSetRepositoryTest.java @@ -27,5 +27,8 @@ public void parseDate() { simpleDateFormat.format(GameSetRepository.parseDate("Aug 31, 2020 6:39:53 PM"))); // old SC24 assertEquals("2013/07/19", simpleDateFormat.format(GameSetRepository.parseDate("19/07/2013"))); // old date + assertEquals("1913/07/14", + simpleDateFormat.format(GameSetRepository.parseDate("1913/07/14"))); // old date + } } \ No newline at end of file diff --git a/playshogi-library-shogi/src/main/java/com/playshogi/library/shogi/models/formats/usf/UsfMoveConverter.java b/playshogi-library-shogi/src/main/java/com/playshogi/library/shogi/models/formats/usf/UsfMoveConverter.java index 057726c8..478e696b 100644 --- a/playshogi-library-shogi/src/main/java/com/playshogi/library/shogi/models/formats/usf/UsfMoveConverter.java +++ b/playshogi-library-shogi/src/main/java/com/playshogi/library/shogi/models/formats/usf/UsfMoveConverter.java @@ -13,7 +13,7 @@ public class UsfMoveConverter { "MATE", "REPT", "NMAT", "++++", "++..", "+...", "====", "-...", "--..", "----", "=88=", "+88-"}; public static final SpecialMoveType[] specialTypes = {null, null, SpecialMoveType.SILENT, SpecialMoveType.RESIGN, - null, + SpecialMoveType.BREAK, SpecialMoveType.JISHOGI, SpecialMoveType.TIMEOUT, SpecialMoveType.ILLEGAL_MOVE, null, SpecialMoveType.CHECKMATE, SpecialMoveType.SENNICHITE, null, null, null, null, null, null, null, null, null, null}; 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 fb6844e0..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 @@ -8,15 +8,13 @@ import com.google.web.bindery.event.shared.binder.EventHandler; import com.playshogi.library.shogi.models.formats.usf.UsfFormat; import com.playshogi.website.gwt.client.SessionInformation; -import com.playshogi.website.gwt.client.events.collections.ListCollectionGamesEvent; -import com.playshogi.website.gwt.client.events.collections.RemoveGameFromCollectionEvent; -import com.playshogi.website.gwt.client.events.collections.SaveCollectionDetailsResultEvent; -import com.playshogi.website.gwt.client.events.collections.SaveGameCollectionDetailsEvent; +import com.playshogi.website.gwt.client.events.collections.*; import com.playshogi.website.gwt.client.events.kifu.ImportGameRecordEvent; import com.playshogi.website.gwt.client.events.user.UserLoggedInEvent; 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.KifuSearchFilterDetails; import com.playshogi.website.gwt.shared.services.KifuService; import com.playshogi.website.gwt.shared.services.KifuServiceAsync; import org.dominokit.domino.ui.notifications.Notification; @@ -25,6 +23,7 @@ public class GameCollectionActivity extends MyAbstractActivity { private final KifuServiceAsync kifuService = GWT.create(KifuService.class); private EventBus eventBus; + private GameCollectionDetailsAndGames games; interface MyEventBinder extends EventBinder { } @@ -65,7 +64,8 @@ public void onFailure(Throwable throwable) { @Override public void onSuccess(GameCollectionDetailsAndGames result) { - GWT.log("GameCollectionActivity: retrieved collection games"); + games = result; + GWT.log("GameCollectionActivity: retrieved collection games: " + result.getGames().length); eventBus.fireEvent(new ListCollectionGamesEvent(result.getGames(), result.getDetails())); } }); @@ -137,6 +137,35 @@ public void onSuccess(final Void unused) { }); } + @EventHandler + public void onSearchKifus(final SearchKifusEvent event) { + GWT.log("GameCollectionActivity Handling SearchKifusEvent"); + + + 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() { fetchData(); } 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 new file mode 100644 index 00000000..c7c0b3e5 --- /dev/null +++ b/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/events/collections/SearchKifusEvent.java @@ -0,0 +1,28 @@ +package com.playshogi.website.gwt.client.events.collections; + +import com.google.web.bindery.event.shared.binder.GenericEvent; +import com.playshogi.library.shogi.models.record.GameResult; + +public class SearchKifusEvent extends GenericEvent { + private final GameResult result; + private final String player; + private final String partialPositionSfen; + + public SearchKifusEvent(final GameResult result, String player, String partialPositionSfen) { + this.result = result; + this.player = player; + this.partialPositionSfen = partialPositionSfen; + } + + public GameResult getResult() { + return result; + } + + 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/ui/GameCollectionView.java b/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/ui/GameCollectionView.java index 2e9839f5..6830dcf8 100644 --- a/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/ui/GameCollectionView.java +++ b/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/ui/GameCollectionView.java @@ -14,9 +14,11 @@ import com.playshogi.website.gwt.client.place.OpeningsPlace; import com.playshogi.website.gwt.client.tables.GameTable; import com.playshogi.website.gwt.client.util.ElementWidget; +import com.playshogi.website.gwt.client.widget.collections.SearchKifuForm; import com.playshogi.website.gwt.client.widget.collections.UploadKifusPopup; import com.playshogi.website.gwt.client.widget.kifu.ImportKifuPanel; import com.playshogi.website.gwt.shared.models.GameCollectionDetails; +import com.playshogi.website.gwt.shared.models.GameDetails; import com.playshogi.website.gwt.shared.models.KifuDetails; import elemental2.dom.HTMLAnchorElement; import elemental2.dom.HTMLDivElement; @@ -29,7 +31,9 @@ import javax.inject.Inject; import javax.inject.Singleton; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; @Singleton public class GameCollectionView extends Composite { @@ -44,6 +48,8 @@ interface MyEventBinder extends EventBinder { private final GameTable gameTable; private final ImportKifuPanel importKifuPanel = new ImportKifuPanel(); private final UploadKifusPopup uploadKifusPopup = new UploadKifusPopup(false, false, true, false, false); + + private final SearchKifuForm searchKifuForm = new SearchKifuForm(); private final SessionInformation sessionInformation; private final AppPlaceHistoryMapper historyMapper; private final HtmlContentBuilder exploreLink; @@ -51,6 +57,8 @@ interface MyEventBinder extends EventBinder { private final Button addKifuButton; private final Button uploadKifuButton; + private final Button searchKifuButton; + private EventBus eventBus; private GameCollectionDetails collectionDetails; @@ -87,6 +95,11 @@ public GameCollectionView(final SessionInformation sessionInformation, final App }) .style().setMarginRight("3em")); + searchKifuButton = Button.createPrimary(Icons.ALL.database_search_mdi()).setContent("Search Kifu(s)"); + root.add(searchKifuButton + .addClickListener(evt -> searchKifuForm.showInPopup()) + .style().setMarginRight("3em")); + exploreLink = Elements.a("#"); root.add(exploreLink.add(Button.createSuccess(Icons.ALL.pie_chart()).setContent("Explore Openings"))); @@ -105,6 +118,7 @@ public void activate(final EventBus eventBus) { gameTable.activate(eventBus); importKifuPanel.activate(eventBus); uploadKifusPopup.activate(eventBus); + searchKifuForm.activate(eventBus); } @EventHandler @@ -122,6 +136,14 @@ public void onCollectionList(final ListCollectionGamesEvent event) { collectionDetails.getId())); exploreLink.attr("href", exploreHRef); + HashSet playerNames = new HashSet<>(); + for (GameDetails detail : event.getDetails()) { + if (detail.getSente() != null) playerNames.add(detail.getSente()); + if (detail.getGote() != null) playerNames.add(detail.getGote()); + } + + searchKifuForm.updatePlayerNames(new ArrayList<>(playerNames)); + if (isAuthor) { newKifuButton.show(); addKifuButton.show(); 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 new file mode 100644 index 00000000..2d7f8cac --- /dev/null +++ b/playshogi-website/playshogi-website-client/src/main/java/com/playshogi/website/gwt/client/widget/collections/SearchKifuForm.java @@ -0,0 +1,77 @@ +package com.playshogi.website.gwt.client.widget.collections; + +import com.google.web.bindery.event.shared.EventBus; +import com.playshogi.library.shogi.models.record.GameResult; +import com.playshogi.website.gwt.client.events.collections.SearchKifusEvent; +import elemental2.dom.HTMLDivElement; +import org.dominokit.domino.ui.button.Button; +import org.dominokit.domino.ui.forms.*; +import org.dominokit.domino.ui.modals.ModalDialog; +import org.jboss.elemento.Elements; +import org.jboss.elemento.HtmlContentBuilder; + +import java.util.List; + +public class SearchKifuForm { + + + LocalSuggestBoxStore playerNames = LocalSuggestBoxStore.create(); + private HtmlContentBuilder div = null; + + 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"); + + gameResult = Select.create("Game Result") + .appendChild(SelectOption.create(null, "Any result")) + .appendChild(SelectOption.create(GameResult.BLACK_WIN, "Black wins")) + .appendChild(SelectOption.create(GameResult.WHITE_WIN, "White wins")) + .appendChild(SelectOption.create(GameResult.OTHER, "Other")) + .appendChild(SelectOption.create(GameResult.UNKNOWN, "Unknown")) + .setSearchable(false) + .selectAt(0); + + div = Elements.div().add(partialSearch).add(playerName).add(gameResult); + + return div; + } + + + public void updatePlayerNames(final List names) { + playerNames.getSuggestions().clear(); + for (String name : names) { + playerNames.addSuggestion(SuggestItem.create(name)); + } + } + + public void showInPopup() { + ModalDialog modal = ModalDialog.create("Search for Kifus").setAutoClose(false); + modal.appendChild(getForm()); + Button closeButton = Button.create("CANCEL").linkify(); + closeButton.addClickListener(evt -> modal.close()); + Button searchButton = Button.create("SEARCH").linkify(); + searchButton.addClickListener(evt -> { + eventBus.fireEvent(new SearchKifusEvent(gameResult.getValue(), playerName.getValue(), + partialSearch.getValue())); + modal.close(); + }); + modal.appendFooterChild(searchButton); + modal.appendFooterChild(closeButton); + modal.open(); + } + + public void activate(final EventBus eventBus) { + this.eventBus = eventBus; + } +} 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);