Browse Source

Edit Matches

master
GAM 4 years ago
parent
commit
6279f412f6
13 changed files with 324 additions and 77 deletions
  1. +2
    -1
      db/db_init.sql
  2. +1
    -1
      src/main/java/app/data/entity/Game.java
  3. +12
    -1
      src/main/java/app/data/entity/GameInfo.java
  4. +38
    -17
      src/main/java/app/data/service/ChessComService.java
  5. +10
    -10
      src/main/java/app/gameimage/GameImageService.java
  6. +43
    -8
      src/main/java/app/navigation/Navigation.java
  7. +14
    -12
      src/main/java/app/navigation/NavigationUtils.java
  8. +11
    -2
      src/main/java/app/utils/ChessComUtils.java
  9. +10
    -1
      src/main/java/app/utils/EntityStringUtils.java
  10. +14
    -6
      src/main/java/app/views/match/MatchView.java
  11. +8
    -2
      src/main/java/app/views/match/components/GameComponent.java
  12. +160
    -11
      src/main/java/app/views/match/components/MatchComponent.java
  13. +1
    -5
      src/main/java/app/views/match/components/utils/GameComponentUtils.java

+ 2
- 1
db/db_init.sql View File

@ -42,7 +42,8 @@ CREATE TABLE "game" (
CREATE TABLE "game_info" (
"id" SERIAL PRIMARY KEY,
"time_control" varchar,
"chess_com_id" varchar
"chess_com_id" varchar,
"fen" varchar
);


+ 1
- 1
src/main/java/app/data/entity/Game.java View File

@ -56,7 +56,7 @@ public class Game {
return Objects.hash(id, player1IsWhite, result);
}
@ManyToOne(cascade=CascadeType.ALL)
@ManyToOne(cascade=CascadeType.DETACH)
@JoinColumn(name = "match", referencedColumnName = "id", nullable = false)
public Match getMatch() {
return match;


+ 12
- 1
src/main/java/app/data/entity/GameInfo.java View File

@ -10,6 +10,7 @@ public class GameInfo {
private String chessComId;
private Game game;
private String timeControl;
private String fen;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@ -42,6 +43,16 @@ public class GameInfo {
this.timeControl = format;
}
@Basic
@Column(name = "fen", nullable = false)
public String getFen() {
return fen;
}
public void setFen(String fen) {
this.fen = fen;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@ -55,7 +66,7 @@ public class GameInfo {
return Objects.hash(id, chessComId, timeControl);
}
@OneToOne(mappedBy = "gameInfo")
@OneToOne(mappedBy = "gameInfo", cascade = CascadeType.ALL)
public Game getGame() {
return game;
}


+ 38
- 17
src/main/java/app/data/service/ChessComService.java View File

@ -23,25 +23,29 @@ public class ChessComService {
private static final Gson gson = new Gson();
private static final String ARCHIVES_ENDPOINT = "https://api.chess.com/pub/player/{username}/games/archives";
private final Map<String, ChessComGame> chessComGameCache = new HashMap<>();
public ChessComService() {
}
@NonNull
public List<Game> getLatestGamesBetweenPlayers(@NonNull Match match, int minAmountOfGames, int maxAmountOfMonths) {
List<Game> list = new ArrayList<>();
List<Game> games = new ArrayList<>();
for (String archiveUrl : getLatestArchiveUrls(match.getPlayer1(), maxAmountOfMonths)) {
list.addAll(getChessComGames(archiveUrl).stream()
List<ChessComGame> chessComGames = getChessComGames(archiveUrl).stream()
.sorted(Comparator.comparingLong(ChessComGame::getEndTime).reversed())
.filter(chessComGame -> ChessComUtils.isGameBetweenPlayers(chessComGame, match))
.filter(ChessComUtils::hasValidTimeControl)
.map(chessComGame -> createGame(chessComGame, match))
.collect(Collectors.toList());
chessComGames.forEach(chessComGame -> chessComGameCache.put(chessComGame.getUrl(), chessComGame));
games.addAll(chessComGames.stream()
.map(chessComGame -> getGame(chessComGame, match))
.collect(Collectors.toList()));
if (list.size() >= minAmountOfGames) {
if (games.size() >= minAmountOfGames) {
break;
}
}
return list;
return games;
} // TODO: find exactly two games of each time control
private List<ChessComGame> getChessComGames(String archiveUrl) {
@ -75,8 +79,13 @@ public class ChessComService {
return archiveUrls;
}
public Optional<Game> getGame(@NonNull String url, @NonNull Match match) {
Optional<ChessComGame> chessComGame = getChessComGame(url, match);
return chessComGame.map(game -> getGame(game, match));
}
@NonNull
private Game createGame(@NonNull ChessComGame chessComGame, @NonNull Match match) {
public Game getGame(@NonNull ChessComGame chessComGame, @NonNull Match match) {
Game game = new Game();
GameInfo gameInfo = new GameInfo();
@ -85,8 +94,9 @@ public class ChessComService {
game.setResult(ChessComUtils.getResult(chessComGame));
game.setGameInfo(gameInfo);
gameInfo.setChessComId(chessComGame.getUrl());
gameInfo.setChessComId(ChessComUtils.getGameId(chessComGame));
gameInfo.setTimeControl(chessComGame.getTimeControl());
gameInfo.setFen(chessComGame.getFen());
gameInfo.setGame(game);
return game;
@ -101,15 +111,26 @@ public class ChessComService {
if (!(game.getMatch().getPlayer1().equals(player) || game.getMatch().getPlayer2().equals(player))) {
throw new IllegalArgumentException("Player must be participating in Game!");
}
for (String archiveUrl : getArchiveUrls(player)) {
Optional<ChessComArchive> chessComArchive = getChessComArchive(archiveUrl);
if (chessComArchive.isEmpty()) {
continue;
}
List<ChessComGame> chessComGames = chessComArchive.get().getGames();
for (ChessComGame chessComGame : chessComGames) {
if (chessComGame.getUrl().equals(game.getGameInfo().getChessComId())) {
return Optional.of(chessComGame);
return getChessComGame(ChessComUtils.getGameURL(game.getGameInfo().getChessComId()), game.getMatch());
}
public Optional<ChessComGame> getChessComGame(@NonNull String url, Match match) {
Optional<ChessComGame> gameFromCache = Optional.ofNullable(chessComGameCache.get(url));
if (gameFromCache.isPresent()) {
return gameFromCache;
}
for (Player player : Set.of(match.getPlayer1(), match.getPlayer2())) {
for (String archiveUrl : getArchiveUrls(player)) {
Optional<ChessComArchive> chessComArchive = getChessComArchive(archiveUrl);
if (chessComArchive.isEmpty()) {
continue;
}
List<ChessComGame> chessComGames = chessComArchive.get().getGames();
for (ChessComGame chessComGame : chessComGames) {
if (chessComGame.getUrl().equals(url)) {
return Optional.of(chessComGame);
}
}
}
}


+ 10
- 10
src/main/java/app/gameimage/GameImageService.java View File

@ -18,31 +18,31 @@ public class GameImageService {
this.chessComService = chessComService;
}
public Optional<String> getVaadinImagePath(Game game) {
return getImagePath(game).map(path -> path.replace("src/main/resources/META-INF/resources/", ""));
}
public Optional<String> getImagePath(Game game) {
public boolean hasImage(Game game) {
String path = GameImageUtils.IMAGE_DEST_PATH_SERVER + getGameNumber(game) + GameImageUtils.EXTENSION;
File f = new File(path);
if(f.isFile()) {
return Optional.of(path);
}
return f.isFile();
}
public boolean createImageIfNotPresent(Game game) {
if (hasImage(game)) return true;
Optional<String> optionalFen = getFen(game);
if (optionalFen.isPresent()) {
GameImageUtils.writeImage(GameImageGenerator.generateImage(optionalFen.get()), getGameNumber(game));
return Optional.of(path);
return true;
}
return Optional.empty();
return false;
}
private String getGameNumber(Game game) {
String[] url = game.getGameInfo().getChessComId().split("/");
return url[url.length -1];
return url[url.length - 1];
}
private Optional<String> getFen(Game game) {
if (game.getGameInfo().getFen() != null) return Optional.of(game.getGameInfo().getFen());
return chessComService.getChessComGame(game).map(ChessComGame::getFen);
}
}

+ 43
- 8
src/main/java/app/navigation/Navigation.java View File

@ -8,11 +8,10 @@ import app.data.service.MatchService;
import app.data.service.MatchdayService;
import app.data.service.SeasonService;
import app.utils.EntityStringUtils;
import com.vaadin.flow.component.*;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.AbstractField;
import com.vaadin.flow.component.HasValue;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.select.Select;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.function.SerializableFunction;
import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.HasUrlParameter;
import com.vaadin.flow.router.WildcardParameter;
@ -48,6 +47,8 @@ public class Navigation implements HasUrlParameter<String> {
private final ValidationLabel validationLabel = new ValidationLabel();
private boolean editFlag = false;
public Navigation(@Autowired SeasonService seasonService,
@Autowired MatchdayService matchdayService,
@Autowired MatchService matchService) {
@ -110,7 +111,7 @@ public class Navigation implements HasUrlParameter<String> {
if (matchEnabled() && matchSelect.getOptionalValue().isPresent())
matchParam = EntityStringUtils.getMatchStringForURL(matchSelect.getValue());
String params = NavigationUtils.getWildcardParam(seasonParam, matchdayParam, matchParam);
String params = NavigationUtils.getWildcardParam(editFlag, seasonParam, matchdayParam, matchParam);
UI.getCurrent().getPage().getHistory().pushState(null, String.format("%s/%s", getRoute(), params));
}
@ -152,7 +153,8 @@ public class Navigation implements HasUrlParameter<String> {
}
private void autoselectSeason() {
if (!seasonEnabled()) throw new IllegalStateException("This method should not be called when season is not enabled!");
if (!seasonEnabled())
throw new IllegalStateException("This method should not be called when season is not enabled!");
if (seasonList.isEmpty()) {
validationLabel.setText("No Seasons in List!");
validationLabel.setValid(false);
@ -162,7 +164,8 @@ public class Navigation implements HasUrlParameter<String> {
}
private void autoselectMatchday() { // TODO: add date stuff and choose depending on date instead!
if (!matchdayEnabled()) throw new IllegalStateException("This method should not be called when matchday is not enabled!");
if (!matchdayEnabled())
throw new IllegalStateException("This method should not be called when matchday is not enabled!");
if (matchdayList.isEmpty()) {
validationLabel.setText("No Matchdays in List!");
validationLabel.setValid(false);
@ -174,7 +177,8 @@ public class Navigation implements HasUrlParameter<String> {
}
private void autoselectMatch() {
if (!matchEnabled()) throw new IllegalStateException("This method should not be called when match is not enabled!");
if (!matchEnabled())
throw new IllegalStateException("This method should not be called when match is not enabled!");
if (matchList.isEmpty()) {
validationLabel.setText("No Matches in List!");
validationLabel.setValid(false);
@ -206,6 +210,7 @@ public class Navigation implements HasUrlParameter<String> {
@Override
public void setParameter(BeforeEvent event, @WildcardParameter String param) {
Map<NavigationLevel, Optional<String>> map = NavigationUtils.getParameterMap(param);
editFlag = NavigationUtils.editFlag(param);
navigate(map.get(NavigationLevel.SEASON), map.get(NavigationLevel.MATCHDAY), map.get(NavigationLevel.MATCH));
}
@ -277,4 +282,34 @@ public class Navigation implements HasUrlParameter<String> {
public MatchService getMatchService() {
return matchService;
}
public boolean editFlag() {
return editFlag;
}
public void setEditFlag(boolean editFlag) {
if (editFlag != this.editFlag) {
this.editFlag = editFlag;
updateUrl();
runnablesToBeRunAfterSelection.forEach(Runnable::run);
}
}
public String getWildcardParam() {
return NavigationUtils.getWildcardParam(
editFlag,
getSeasonParam().orElse(null),
getMatchdayParam().orElse(null),
getMatchParam().orElse(null));
}
public Optional<String> getSeasonParam() {
return getSelectedSeason().map(EntityStringUtils::getSeasonStringForURL);
}
public Optional<String> getMatchdayParam() {
return getSelectedMatchday().map(EntityStringUtils::getMatchdayStringForURL);
}
public Optional<String> getMatchParam() {
return getSelectedMatch().map(EntityStringUtils::getMatchStringForURL);
}
}

+ 14
- 12
src/main/java/app/navigation/NavigationUtils.java View File

@ -1,5 +1,6 @@
package app.navigation;
import app.utils.EntityStringUtils;
import com.vaadin.flow.router.WildcardParameter;
import org.springframework.lang.NonNull;
@ -10,6 +11,7 @@ import java.util.Optional;
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
class NavigationUtils {
private static final String EDIT = "edit";
private NavigationUtils() {
}
@ -18,24 +20,23 @@ class NavigationUtils {
static Map<NavigationLevel, Optional<String>> getParameterMap(@WildcardParameter String param) {
Map<NavigationLevel, Optional<String>> map = new HashMap<>();
String[] params = param.split("/");
switch (params.length) {
case 3:
map.put(NavigationLevel.MATCH, Optional.of(params[2]));
case 2:
map.put(NavigationLevel.MATCHDAY, Optional.of(params[1]));
case 1:
map.put(NavigationLevel.SEASON, Optional.of(params[0]));
default:
break;
}
if (params.length >= 1 && !params[0].equals(EDIT)) map.put(NavigationLevel.SEASON, Optional.of(params[0]));
if (params.length >= 2 && !params[1].equals(EDIT)) map.put(NavigationLevel.MATCHDAY, Optional.of(params[1]));
if (params.length >= 3 && !params[2].equals(EDIT)) map.put(NavigationLevel.MATCH, Optional.of(params[2]));
map.putIfAbsent(NavigationLevel.MATCH, Optional.empty());
map.putIfAbsent(NavigationLevel.MATCHDAY, Optional.empty());
map.putIfAbsent(NavigationLevel.SEASON, Optional.empty());
return map;
}
static boolean editFlag(@WildcardParameter String param) {
String[] params = param.split("/");
return params[params.length - 1].equals(EDIT);
}
@NonNull
static String getWildcardParam(String... params) {
static String getWildcardParam(boolean editFlag, String... params) {
StringBuilder stringBuilder = new StringBuilder();
for (String param : params) {
if (param == null || param.equals("")) {
@ -43,6 +44,7 @@ class NavigationUtils {
}
stringBuilder.append(param).append("/");
}
if (editFlag) stringBuilder.append(EDIT).append("/");
return stringBuilder.toString();
}
@ -51,7 +53,7 @@ class NavigationUtils {
return Optional.empty();
}
return objectList.stream()
.filter(match -> match.toString().equals(param.get()))
.filter(object -> EntityStringUtils.getObjectStringForURL(object).equals(param.get()))
.findFirst();
}
}

+ 11
- 2
src/main/java/app/utils/ChessComUtils.java View File

@ -8,7 +8,7 @@ import org.springframework.lang.NonNull;
public class ChessComUtils {
private static final String GAME_LINK = "https://www.chess.com/live/game/{gameId}";
private static final String GAME_LINK = "https://www.chess.com/game/live/{gameId}";
private ChessComUtils() {
}
@ -51,8 +51,17 @@ public class ChessComUtils {
return false;
}
public static String getGameLink(Game game) {
public static String getGameURL(Game game) {
String gameId = game.getGameInfo().getChessComId();
return getGameURL(gameId);
}
public static String getGameURL(String gameId) {
return GAME_LINK.replace("{gameId}", gameId);
}
public static String getGameId(ChessComGame game) {
String[] fields = game.getUrl().split("/");
return fields[fields.length - 1];
}
}

+ 10
- 1
src/main/java/app/utils/EntityStringUtils.java View File

@ -4,6 +4,7 @@ import app.data.entity.Match;
import app.data.entity.Matchday;
import app.data.entity.Player;
import app.data.entity.Season;
import org.springframework.lang.NonNull;
public class EntityStringUtils {
private EntityStringUtils() {
@ -17,7 +18,7 @@ public class EntityStringUtils {
return player.getNickname().toLowerCase();
}
public static String getSeasonString(Season season) {
public static String getSeasonString(@NonNull Season season) {
String string = season.getYearStart().toString();
if (!season.getYearEnd().equals(season.getYearStart())) {
string += "-" + season.getYearEnd().toString();
@ -25,6 +26,14 @@ public class EntityStringUtils {
return string;
}
public static String getObjectStringForURL(Object object) {
if (object instanceof Player) return getPlayerStringForURL((Player) object);
if (object instanceof Season) return getSeasonStringForURL((Season) object);
if (object instanceof Matchday) return getMatchdayStringForURL((Matchday) object);
if (object instanceof Match) return getMatchStringForURL((Match) object);
throw new IllegalStateException(String.format("Cannot get Object String for URL for Type %s!", object.getClass().getSimpleName()));
}
public static String getSeasonStringForURL(Season season) {
return getSeasonString(season);
}


+ 14
- 6
src/main/java/app/views/match/MatchView.java View File

@ -1,6 +1,9 @@
package app.views.match;
import app.data.service.MatchService;
import app.data.service.ChessComService;
import app.data.service.GameInfoService;
import app.data.service.GameService;
import app.gameimage.GameImageService;
import app.navigation.NavigationLevel;
import app.navigation.NavigationService;
import app.views.main.MainView;
@ -16,14 +19,19 @@ import org.springframework.beans.factory.annotation.Autowired;
@PageTitle("Schachliga DACH - Results - Matches")
public class MatchView extends NavigationViewBase {
private final MatchService matchService;
private final ChessComService chessComService;
private final GameService gameService;
private final GameInfoService gameInfoService;
private final GameImageService gameImageService;
private MatchComponent matchComponent;
public MatchView(@Autowired NavigationService navigationService,
@Autowired MatchService matchService) {
@Autowired ChessComService chessComService, @Autowired GameService gameService, GameInfoService gameInfoService, GameImageService gameImageService) {
super(navigationService, "match", NavigationLevel.MATCH);
this.matchService = matchService;
this.chessComService = chessComService;
this.gameService = gameService;
this.gameInfoService = gameInfoService;
this.gameImageService = gameImageService;
addClassName("match-view");
@ -35,7 +43,7 @@ public class MatchView extends NavigationViewBase {
////////////
private void configureLayout() {
matchComponent = new MatchComponent(navigation);
matchComponent = new MatchComponent(navigation, chessComService, gameService, gameInfoService, gameImageService);
add(matchComponent);
}


+ 8
- 2
src/main/java/app/views/match/components/GameComponent.java View File

@ -1,6 +1,7 @@
package app.views.match.components;
import app.data.entity.Game;
import app.gameimage.GameImageService;
import app.views.match.components.utils.GameComponentUtils;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Div;
@ -9,9 +10,12 @@ import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import org.springframework.beans.factory.annotation.Autowired;
public class GameComponent extends Div {
private final GameImageService gameImageService;
private final Game game;
private final HorizontalLayout inner = new HorizontalLayout();
@ -19,7 +23,8 @@ public class GameComponent extends Div {
private final VerticalLayout left = new VerticalLayout();
private final Div right = new Div();
public GameComponent(Game game) {
public GameComponent(Game game, @Autowired GameImageService gameImageService) {
this.gameImageService = gameImageService;
this.game = game;
addClassName("wrapper");
@ -56,7 +61,8 @@ public class GameComponent extends Div {
private void configureRight() {
right.addClassName("game-image-div");
Image image = new Image(GameComponentUtils.getImagePath(game), "Could not find game image.");
gameImageService.createImageIfNotPresent(game);
Image image = new Image(GameComponentUtils.getImagePath(game), "Could not load game image.");
right.add(image);
image.setWidthFull();
image.setHeightFull();


+ 160
- 11
src/main/java/app/views/match/components/MatchComponent.java View File

@ -3,36 +3,91 @@ package app.views.match.components;
import app.data.bean.CalculatedMatch;
import app.data.entity.Game;
import app.data.entity.Match;
import app.data.service.ChessComService;
import app.data.service.GameInfoService;
import app.data.service.GameService;
import app.gameimage.GameImageService;
import app.navigation.Navigation;
import app.utils.ChessComUtils;
import app.utils.EntityComponentUtils;
import app.utils.StringUtils;
import app.views.navigation.interfaces.ContentConfigurable;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.FlexLayout;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.shared.Registration;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;
public class MatchComponent extends Div implements ContentConfigurable {
private final Navigation navigation;
private final ChessComService chessComService;
private final GameService gameService;
private final GameInfoService gameInfoService;
private final GameImageService gameImageService;
private final VerticalLayout headerLayout = new VerticalLayout();
private final HorizontalLayout headerPlayersLayout = new HorizontalLayout();
private final Label headerResultLabel = new Label();
private final FlexLayout gamesLayout = new FlexLayout();
public MatchComponent(Navigation navigation) {
private final VerticalLayout noGamesLayout = new VerticalLayout();
private final FlexLayout editLayoutWrapper = new FlexLayout();
private final VerticalLayout editLayout = new VerticalLayout();
private final ArrayList<TextField> editTextFields = new ArrayList<>();
private final Button editSubmitButton = new Button("Submit", new Icon(VaadinIcon.CHECK));
private Registration editSubmitButtonRegistration;
private final Button editCancelButton = new Button("Cancel", new Icon(VaadinIcon.CLOSE));
private Registration editCancelButtonRegistration;
private final Button chessComButton = new Button("Autofill with the latest 6 games between the players", new Icon(VaadinIcon.MAGIC));
private Registration chessComButtonButtonRegistration;
public MatchComponent(Navigation navigation,
@Autowired ChessComService chessComService,
@Autowired GameService gameService,
@Autowired GameInfoService gameInfoService,
@Autowired GameImageService gameImageService) {
this.navigation = navigation;
this.chessComService = chessComService;
this.gameService = gameService;
this.gameInfoService = gameInfoService;
this.gameImageService = gameImageService;
add(headerLayout);
add(headerLayout, gamesLayout);
configureHeaderLayout();
configureGamesLayout();
configureNoGamesLayout();
configureEditLayout();
}
private void configureNoGamesLayout() {
Label label = new Label("No games for this match in the database.");
Button button = new Button("Add games", new Icon(VaadinIcon.PLUS));
button.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
button.addClickListener(event -> {
navigation.setEditFlag(true);
remove(noGamesLayout);
});
noGamesLayout.add(label, button);
noGamesLayout.setAlignItems(FlexComponent.Alignment.CENTER);
}
private void configureHeaderLayout() {
@ -49,23 +104,112 @@ public class MatchComponent extends Div implements ContentConfigurable {
gamesLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
}
private void configureEditLayout() {
editLayoutWrapper.add(editLayout);
editLayoutWrapper.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
editLayout.setAlignItems(FlexComponent.Alignment.CENTER);
editLayout.setWidth("");
editLayout.addClassName("wrapper");
editLayout.add(chessComButton);
for (int i = 0; i < 6; i++) {
TextField textField = new TextField();
textField.setWidth("23em");
HorizontalLayout horizontalLayout = new HorizontalLayout(new Label(String.format("Game %d:", i + 1)), textField);
horizontalLayout.setAlignItems(FlexComponent.Alignment.CENTER);
horizontalLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
editLayout.add(horizontalLayout);
editTextFields.add(textField);
}
editSubmitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
HorizontalLayout buttonLayout = new HorizontalLayout();
buttonLayout.setAlignItems(FlexComponent.Alignment.CENTER);
buttonLayout.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
buttonLayout.add(editSubmitButton, editCancelButton);
editLayout.add(buttonLayout);
}
@Override
public void configureContent() {
try {
Match match = navigation.getSelectedMatch().orElseThrow();
configureHeaderContent(match);
gamesLayout.removeAll();
for (Game game : match.getGames()) {
gamesLayout.add(new GameComponent(game));
}
configureMainContent(match);
} catch (NoSuchElementException e) {
gamesLayout.removeAll();
add(navigation.getValidationLabel());
}
}
private void configureMainContent(Match match) {
if (navigation.editFlag()) {
remove(gamesLayout);
add(editLayoutWrapper);
configureEditContent(match);
return;
}
remove(editLayoutWrapper);
configureGamesContent(match);
}
private void configureEditContent(Match match) {
List<Game> games = new ArrayList<>(match.getGames());
// clear text fields
for (TextField textField : editTextFields) {
textField.setValue("");
}
// fill text fields;
for (int i = 0; i < Math.min(games.size(), 6); i++)
editTextFields.get(i).setValue(ChessComUtils.getGameURL(games.get(i)));
if (chessComButtonButtonRegistration != null) chessComButtonButtonRegistration.remove();
chessComButtonButtonRegistration = chessComButton.addClickListener(event -> {
List<Game> gamesBetweenPlayers = chessComService.getLatestGamesBetweenPlayers(match, 6, 2);
for (int i = 0; i < Math.min(gamesBetweenPlayers.size(), 6); i++) {
editTextFields.get(i).setValue(ChessComUtils.getGameURL(gamesBetweenPlayers.get(i)));
}
});
if (editSubmitButtonRegistration != null) editSubmitButtonRegistration.remove();
editSubmitButtonRegistration = editSubmitButton.addClickListener(event -> {
match.getGames().clear(); // TODO: delete old games from database as well
for (TextField textField : editTextFields) {
Optional<Game> game = chessComService.getGame(textField.getValue(), match); // TODO: handle this when Optional is empty!
game.ifPresent(value -> match.getGames().add(value));
}
match.getGames().forEach(game -> gameInfoService.update(game.getGameInfo()));
match.getGames().forEach(gameImageService::createImageIfNotPresent);
navigation.setEditFlag(false);
});
if (editCancelButtonRegistration != null) editCancelButtonRegistration.remove();
editCancelButtonRegistration = editCancelButton.addClickListener(event ->
UI.getCurrent().navigate(String.format("matchday/%s", navigation.getWildcardParam().replace("edit/", ""))));
}
private void configureGamesContent(Match match) {
if (match.getGames().isEmpty()) {
remove(gamesLayout);
add(noGamesLayout);
return;
}
remove(noGamesLayout);
add(gamesLayout);
gamesLayout.removeAll();
for (Game game : match.getGames()) {
gamesLayout.add(new GameComponent(game, gameImageService));
}
}
private void configureHeaderContent(Match match) {
CalculatedMatch calculatedMatch = navigation.getMatchService().getCalculatedMatch(match);
@ -76,7 +220,12 @@ public class MatchComponent extends Div implements ContentConfigurable {
headerPlayersLayout.removeAll();
headerPlayersLayout.add(player1, vs, player2);
headerResultLabel.setText(String.format("%s",
StringUtils.getResultString("-", calculatedMatch.getScore1(), calculatedMatch.getScore2())));
if (match.getGames().isEmpty() || navigation.editFlag()) {
headerLayout.remove(headerResultLabel);
} else {
headerLayout.add(headerResultLabel);
headerResultLabel.setText(String.format("%s",
StringUtils.getResultString("-", calculatedMatch.getScore1(), calculatedMatch.getScore2())));
}
}
}

+ 1
- 5
src/main/java/app/views/match/components/utils/GameComponentUtils.java View File

@ -5,9 +5,6 @@ import app.data.entity.Player;
import app.gameimage.GameImageUtils;
import app.utils.ChessComUtils;
import app.utils.EntityComponentUtils;
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.html.Div;
@ -19,7 +16,6 @@ import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class GameComponentUtils {
private GameComponentUtils() {
@ -139,7 +135,7 @@ public class GameComponentUtils {
button.addClickListener(event ->
button.getUI().ifPresent(ui ->
ui.getPage().open(ChessComUtils.getGameLink(game), "_blank")));
ui.getPage().open(ChessComUtils.getGameURL(game), "_blank")));
return button;
}


Loading…
Cancel
Save