|
package app.data.service;
|
|
|
|
import app.data.chesscom.ChessComArchive;
|
|
import app.data.chesscom.ChessComArchiveList;
|
|
import app.data.chesscom.ChessComGame;
|
|
import app.data.entity.Game;
|
|
import app.data.entity.GameInfo;
|
|
import app.data.entity.Match;
|
|
import app.data.entity.Player;
|
|
import app.utils.ChessComUtils;
|
|
import app.utils.HttpUtils;
|
|
import com.google.gson.Gson;
|
|
import org.springframework.lang.NonNull;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import java.util.*;
|
|
import java.util.stream.Collectors;
|
|
|
|
@Service
|
|
public class ChessComService {
|
|
// TODO: make everything nullsafe
|
|
|
|
private static final Gson gson = new Gson();
|
|
private static final String ARCHIVES_ENDPOINT = "https://api.chess.com/pub/player/{username}/games/archives";
|
|
|
|
public ChessComService() {
|
|
}
|
|
|
|
@NonNull
|
|
public List<Game> getLatestGamesBetweenPlayers(@NonNull Match match, int minAmountOfGames, int maxAmountOfMonths) {
|
|
List<Game> list = new ArrayList<>();
|
|
for (String archiveUrl : getLatestArchiveUrls(match.getPlayer1(), maxAmountOfMonths)) {
|
|
list.addAll(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()));
|
|
|
|
if (list.size() >= minAmountOfGames) {
|
|
break;
|
|
}
|
|
}
|
|
return list;
|
|
} // TODO: find exactly two games of each time control
|
|
|
|
private List<ChessComGame> getChessComGames(String archiveUrl) {
|
|
List<ChessComGame> list = new ArrayList<>();
|
|
getChessComArchive(archiveUrl).ifPresent(chessComArchive -> list.addAll(chessComArchive.getGames()));
|
|
return list;
|
|
}
|
|
|
|
private Optional<ChessComArchive> getChessComArchive(String archiveUrl) {
|
|
String unpreparedJson = HttpUtils.getJson(archiveUrl);
|
|
if (unpreparedJson == null) {
|
|
return Optional.empty();
|
|
}
|
|
String preparedJson = ChessComUtils.getPreparedArchiveJson(unpreparedJson);
|
|
return Optional.of(gson.fromJson(preparedJson, ChessComArchive.class));
|
|
}
|
|
|
|
private List<String> getLatestArchiveUrls(@NonNull Player player, int maxAmountOfMonths) {
|
|
List<String> archiveUrls = getArchiveUrls(player);
|
|
if (archiveUrls.size() >= maxAmountOfMonths) {
|
|
archiveUrls = archiveUrls.subList(0, maxAmountOfMonths);
|
|
}
|
|
return archiveUrls;
|
|
}
|
|
|
|
private List<String> getArchiveUrls(@NonNull Player player) {
|
|
String endPoint = ARCHIVES_ENDPOINT.replace("{username}", ChessComUtils.getUsernameForUrl(player));
|
|
|
|
List<String> archiveUrls = gson.fromJson(HttpUtils.getJson(endPoint), ChessComArchiveList.class).getArchives();
|
|
archiveUrls.sort(Collections.reverseOrder());
|
|
return archiveUrls;
|
|
}
|
|
|
|
@NonNull
|
|
private Game createGame(@NonNull ChessComGame chessComGame, @NonNull Match match) {
|
|
Game game = new Game();
|
|
GameInfo gameInfo = new GameInfo();
|
|
|
|
game.setMatch(match);
|
|
game.setPlayer1IsWhite(chessComGame.getWhite().getUsername().equals(match.getPlayer1().getNickname()));
|
|
game.setResult(ChessComUtils.getResult(chessComGame));
|
|
game.setGameInfo(gameInfo);
|
|
|
|
gameInfo.setChessComId(chessComGame.getUrl());
|
|
gameInfo.setTimeControl(chessComGame.getTimeControl());
|
|
gameInfo.setGame(game);
|
|
|
|
return game;
|
|
}
|
|
|
|
public Optional<ChessComGame> getChessComGame(@NonNull Game game) {
|
|
return getChessComGame(game, game.getMatch().getPlayer1())
|
|
.or(() -> getChessComGame(game, game.getMatch().getPlayer2()));
|
|
}
|
|
|
|
private Optional<ChessComGame> getChessComGame(@NonNull Game game, Player player) {
|
|
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 Optional.empty();
|
|
}
|
|
|
|
}
|