You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

119 lines
4.7 KiB

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();
}
}