Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,20 @@ public class GameHistory extends ApiMessage {

private final List<GameMessage> messages;

private final boolean isTrainingGame;
@JsonCreator
public GameHistory(
@JsonProperty("gameId") String gameId,
@JsonProperty("playerNames") String[] playerNames,
@JsonProperty("gameDate") LocalDateTime gameDate,
@JsonProperty("messages") List<GameMessage> messages) {
@JsonProperty("messages") List<GameMessage> messages,
@JsonProperty("isTrainingGame") boolean isTrainingGame) {

this.gameId = gameId;
this.playerNames = playerNames;
this.gameDate = gameDate;
this.messages = messages;
this.isTrainingGame = isTrainingGame;
}

public String getGameId() {
Expand All @@ -51,4 +55,8 @@ public LocalDateTime getGameDate() {
public List<GameMessage> getMessages() {
return messages;
}

public boolean isTrainingGame() {
return isTrainingGame;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void testSerialization() throws Exception {
List<GameMessage> gameMessages = new ArrayList<>();
gameMessages.add(new GameStartingEvent(gameId, 3, 46, 34, new GameSettings()));

GameHistory gh = new GameHistory(gameId, players, now, gameMessages);
GameHistory gh = new GameHistory(gameId, players, now, gameMessages, false);

String msg = ApiMessageParser.encodeMessage(gh);
System.out.println(msg);
Expand Down
3 changes: 1 addition & 2 deletions app/docs/elasticsearch.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ each field and if there are any special index options.
Generally for String types we have choosen the index: "not_analyzed". This
means that words will not be split.

There are three indexes in Elasticsearch: clientinfo, gamehistory and
gameevent.
There are three indexes in Elasticsearch: clientinfo, tournamenthistory, tournamentevent, gamehistory and gameevent.

Since it is not possible to change the mapping after it has been created
it is important to define this before the server starts storing data.
Expand Down
12 changes: 10 additions & 2 deletions app/src/main/java/se/cygni/paintbot/event/InternalGameEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@ public class InternalGameEvent {
private final long tstamp;
private GameMessage gameMessage;

public InternalGameEvent(long tstamp) {
private final boolean isTraining;

public InternalGameEvent(long tstamp, boolean isTraining) {
this.tstamp = tstamp;
this.isTraining = isTraining;
}

public InternalGameEvent(long tstamp, GameMessage gameMessage) {
public InternalGameEvent(long tstamp, GameMessage gameMessage, boolean isTraining) {
this.tstamp = tstamp;
this.gameMessage = gameMessage;
this.isTraining = isTraining;
}

public long getTstamp() {
Expand All @@ -31,4 +35,8 @@ public void onGameAborted(String gameId) {
public void onGameChanged(String gameId) {
this.gameMessage = GameMessageConverter.onGameChanged(gameId);
}

public boolean isTraining() {
return isTraining;
}
}
8 changes: 6 additions & 2 deletions app/src/main/java/se/cygni/paintbot/game/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ public boolean isEnded() {
return gameEngine.isGameComplete();
}

public boolean isTrainingGame() {
return trainingGame;
}

public GameResult getGameResult() {
return gameEngine.getGameResult();
}
Expand Down Expand Up @@ -233,14 +237,14 @@ public void abort() {
playerManager.clear();
gameEngine.abort();

InternalGameEvent gevent = new InternalGameEvent(System.currentTimeMillis());
InternalGameEvent gevent = new InternalGameEvent(System.currentTimeMillis(), this.trainingGame);
gevent.onGameAborted(getGameId());
globalEventBus.post(gevent);
globalEventBus.post(gevent.getGameMessage());
}

public void publishGameChanged() {
InternalGameEvent gevent = new InternalGameEvent(System.currentTimeMillis());
InternalGameEvent gevent = new InternalGameEvent(System.currentTimeMillis(), this.trainingGame);
gevent.onGameChanged(getGameId());
globalEventBus.post(gevent);
}
Expand Down
5 changes: 3 additions & 2 deletions app/src/main/java/se/cygni/paintbot/game/GameEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ private void notifyPlayers(Set<IPlayer> players, GameMessage message) {

InternalGameEvent gevent = new InternalGameEvent(
System.currentTimeMillis(),
message);
message,
this.gameFeatures.isTrainingGame());
globalEventBus.post(gevent);
}

Expand Down Expand Up @@ -304,7 +305,7 @@ public GameResult getGameResult() {
}

public void publishGameChanged() {
InternalGameEvent gevent = new InternalGameEvent(System.currentTimeMillis());
InternalGameEvent gevent = new InternalGameEvent(System.currentTimeMillis(), this.gameFeatures.isTrainingGame());
gevent.onGameChanged(gameId);
globalEventBus.post(gevent);
}
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/se/cygni/paintbot/game/GameManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ private void registerGame(Game game) {
log.info("Registered new game, posting to GlobalEventBus...");
globalEventBus.post(new InternalGameEvent(
System.currentTimeMillis(),
new GameCreatedEvent(game.getGameId())));
new GameCreatedEvent(game.getGameId()),
game.isTrainingGame()));
}

@Subscribe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,18 @@ private GameHistory getGameHistory(String gameId) {
gameId,
getPlayersForGame(gameId),
extractGameDate(gameId),
getGameMessagesForGame(gameId));
getGameMessagesForGame(gameId),
isTrainingGame(gameId));
}

private boolean isTrainingGame(String gameId) {
Optional<InternalGameEvent> firstMapUpdate = getFirstInternalGameEvent(gameId);

if(firstMapUpdate.isPresent()) {
return firstMapUpdate.get().isTraining();
}

return false;
}

private List<GameMessage> getGameMessagesForGame(String gameId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ public class GameHistoryStorageElastic implements GameHistoryStorage {
@Value("${paintbot.elastic.gamehistory.type}")
private String gameHistoryType;

@Value("${paintbot.elastic.tournamenthistory.index}")
private String tournamentHistoryIndex;

@Value("${paintbot.elastic.tournamenthistory.type}")
private String tournamentHistoryType;

@Value("${paintbot.elastic.tournamentevent.index}")
private String tournamentEventIndex;

@Value("${paintbot.elastic.tournamentevent.type}")
private String tournamentEventType;

@Value("${paintbot.elastic.gameevent.index}")
private String gameEventIndex;

Expand All @@ -71,7 +83,14 @@ public void addGameHistory(GameHistory gameHistory) {

String eventId = UUID.randomUUID().toString();
try {
IndexRequest indexRequest = new IndexRequest(gameEventIndex, gameEventType, eventId);
IndexRequest indexRequest;

if (gameHistory.isTrainingGame()) {
indexRequest = new IndexRequest(gameEventIndex, gameEventType, eventId);
} else {
indexRequest = new IndexRequest(tournamentEventIndex, tournamentEventType, eventId);
}

String msg = GameMessageParser.encodeMessage(gameMessage);
indexRequest.source(msg, XContentType.JSON);
elasticClient.index(indexRequest);
Expand All @@ -83,10 +102,17 @@ public void addGameHistory(GameHistory gameHistory) {
GameHistoryPersisted ghp = new GameHistoryPersisted(
gameHistory.getGameId(),
gameHistory.getPlayerNames(),
gameHistory.getGameDate()
gameHistory.getGameDate(),
gameHistory.isTrainingGame()
);

IndexRequest indexRequest = new IndexRequest(gameHistoryIndex, gameHistoryType, gameHistory.getGameId());
IndexRequest indexRequest;
if (gameHistory.isTrainingGame()) {
indexRequest = new IndexRequest(gameHistoryIndex, gameHistoryType, gameHistory.getGameId());
} else {
indexRequest = new IndexRequest(tournamentHistoryIndex, tournamentHistoryType, gameHistory.getGameId());
}

String msg = ApiMessageParser.encodeMessage(ghp);
indexRequest.source(msg, XContentType.JSON);
elasticClient.index(indexRequest);
Expand All @@ -104,6 +130,16 @@ public Optional<GameHistory> getGameHistory(String gameId) {

try {
SearchResponse esResponse = elasticClient.search(searchRequest);

if (esResponse.getHits().totalHits == 0) {
searchRequest = new SearchRequest(tournamentHistoryIndex);
searchSourceBuilder = new SearchSourceBuilder()
.query(QueryBuilders.idsQuery(tournamentHistoryType).addIds(gameId));
searchRequest.source(searchSourceBuilder);

esResponse = elasticClient.search(searchRequest);
}

if (esResponse.getHits().totalHits > 0) {
GameHistoryPersisted ghp = (GameHistoryPersisted) ApiMessageParser.decodeMessage(esResponse.getHits().getAt(0).getSourceAsString());
List<GameMessage> gameMessages = getGameEventsForGame(gameId);
Expand All @@ -112,7 +148,8 @@ public Optional<GameHistory> getGameHistory(String gameId) {
ghp.getGameId(),
ghp.getPlayerNames(),
ghp.getGameDate(),
gameMessages
gameMessages,
ghp.isTrainingGame()
);

return Optional.of(gameHistory);
Expand Down Expand Up @@ -143,6 +180,21 @@ private List<GameMessage> getGameEventsForGame(String gameId) {
return messages;
}

if (scrollResp.getHits().totalHits == 0) {
searchRequest = new SearchRequest(tournamentEventIndex)
.scroll(new TimeValue(60000));
searchSourceBuilder = new SearchSourceBuilder()
.query(qb)
.size(200);
searchRequest.source(searchSourceBuilder);

try {
scrollResp = elasticClient.search(searchRequest);
} catch (IOException e) {
log.error("Failed to search ElasticSearch");
return messages;
}
}

//Scroll until no hits are returned
while (true) {
Expand Down Expand Up @@ -198,6 +250,12 @@ private GameHistorySearchResult getGameHistorySearchResult(SearchSourceBuilder s
List<GameHistorySearchItem> items = new ArrayList<>();
try {
SearchResponse esResponse = elasticClient.search(searchRequest);
if (esResponse.getHits().totalHits == 0) {
searchRequest = new SearchRequest(tournamentHistoryIndex);
searchRequest.source(searchSourceBuilder);

esResponse = elasticClient.search(searchRequest);
}

Iterator<SearchHit> searchHitIterator = esResponse.getHits().iterator();
int counter = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class GameHistoryStorageInMemory implements GameHistoryStorage {
private final EventBus eventBus;

private List<GameHistory> gameHistories = Collections.synchronizedList(new ArrayList<>());
private List<GameHistory> tournamentHistories = Collections.synchronizedList(new ArrayList<>());

@Autowired
public GameHistoryStorageInMemory(EventBus eventBus) {
Expand All @@ -43,15 +44,28 @@ public GameHistoryStorageInMemory(EventBus eventBus) {
@Subscribe
public void addGameHistory(GameHistory gameHistory) {
log.debug("Adding GameHistory to memory!");
gameHistories.add(gameHistory);
if (gameHistory.isTrainingGame()) {
gameHistories.add(gameHistory);
} else {
tournamentHistories.add(gameHistory);
}
}

@Override
public Optional<GameHistory> getGameHistory(String gameId) {
return gameHistories
Optional<GameHistory> gh = gameHistories
.stream()
.filter(gameHistory -> gameHistory.getGameId().equals(gameId))
.findFirst();

if (gh.isEmpty()) {
return tournamentHistories
.stream()
.filter(gameHistory -> gameHistory.getGameId().equals(gameId))
.findFirst();
}

return gh;
}

@Override
Expand All @@ -70,6 +84,20 @@ public GameHistorySearchResult listGamesWithPlayer(String playerName) {
})
.collect(Collectors.toList());

if (items.isEmpty()) {
items = tournamentHistories
.stream()
.filter(gameHistory -> ArrayUtils.contains(gameHistory.getPlayerNames(), playerName))
.map(gameHistory -> {
return new GameHistorySearchItem(
gameHistory.getGameId(),
gameHistory.getPlayerNames(),
gameHistory.getGameDate()
);
})
.collect(Collectors.toList());
}

result.setItems(items);
return result;
}
Expand All @@ -83,6 +111,17 @@ public GameHistorySearchResult getHistoricGames() {
gameHistory.getPlayerNames(),
gameHistory.getGameDate()))
.collect(Collectors.toList()));

if (games.getItems().isEmpty()) {
games = new GameHistorySearchResult(
tournamentHistories.stream()
.map(gameHistory -> new GameHistorySearchItem(
gameHistory.getGameId(),
gameHistory.getPlayerNames(),
gameHistory.getGameDate()))
.collect(Collectors.toList()));
}

return games;
}

Expand All @@ -92,6 +131,11 @@ private void removeOldGames() {
GameHistory gameHistory = gameHistories.remove(0);
log.debug("Removed gameId: {}", gameHistory.getGameId());
}

while (tournamentHistories.size() > MAX_NOOF_GAMES_IN_MEMORY - 1) {
GameHistory gameHistory = tournamentHistories.remove(0);
log.debug("Removed gameId: {}", gameHistory.getGameId());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@ public class GameHistoryPersisted extends ApiMessage {

private final LocalDateTime gameDate;

private final boolean isTrainingGame;
@JsonCreator
public GameHistoryPersisted(
@JsonProperty("gameId") String gameId,
@JsonProperty("playerNames") String[] playerNames,
@JsonProperty("gameDate") LocalDateTime gameDate) {
@JsonProperty("gameDate") LocalDateTime gameDate,
@JsonProperty("isTrainingGame") boolean isTrainingGame) {

this.gameId = gameId;
this.playerNames = playerNames;
this.gameDate = gameDate;
this.isTrainingGame = isTrainingGame;
}

public String getGameId() {
Expand All @@ -42,4 +45,8 @@ public String[] getPlayerNames() {
public LocalDateTime getGameDate() {
return gameDate;
}

public boolean isTrainingGame() {
return isTrainingGame;
}
}
Loading