Added json summary generation after replay is compiled.
This commit is contained in:
@@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON;
|
||||
import com.gempukku.lotro.async.HttpProcessingException;
|
||||
import com.gempukku.lotro.async.ResponseWriter;
|
||||
import com.gempukku.lotro.game.Player;
|
||||
import com.google.gson.Gson;
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
import io.netty.handler.codec.http.HttpRequest;
|
||||
import io.netty.handler.codec.http.QueryStringDecoder;
|
||||
@@ -14,7 +13,6 @@ import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
|
||||
public class PlayerInfoRequestHandler extends LotroServerRequestHandler implements UriRequestHandler {
|
||||
private final Gson JsonConvert = new Gson();
|
||||
|
||||
private static final Logger _log = Logger.getLogger(PlayerInfoRequestHandler.class);
|
||||
|
||||
|
||||
@@ -16,10 +16,7 @@ public class EventSerializer {
|
||||
public Node serializeEvent(Document doc, GameEvent gameEvent) {
|
||||
Element eventElem = doc.createElement("ge");
|
||||
eventElem.setAttribute("type", gameEvent.getType().getCode());
|
||||
//TODO:
|
||||
// - figure out a better date/time format for the log
|
||||
// - import the json replay info into gemp
|
||||
eventElem.setAttribute("timestamp", gameEvent.getTimestamp().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||||
eventElem.setAttribute("timestamp", gameEvent.getTimestamp().format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss.SSSS")));
|
||||
|
||||
if (gameEvent.getBlueprintId() != null)
|
||||
eventElem.setAttribute("blueprintId", gameEvent.getBlueprintId());
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.util.Objects;
|
||||
public class DbGameHistoryDAO implements GameHistoryDAO {
|
||||
private final DbAccess _dbAccess;
|
||||
private final DateTimeFormatter _dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
private final DateTimeFormatter _dateTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
|
||||
|
||||
public DbGameHistoryDAO(DbAccess dbAccess) {
|
||||
_dbAccess = dbAccess;
|
||||
@@ -49,8 +50,8 @@ public class DbGameHistoryDAO implements GameHistoryDAO {
|
||||
.addParameter("tournament", tournament)
|
||||
.addParameter("winner_deck_name", winnerDeckName)
|
||||
.addParameter("loser_deck_name", loserDeckName)
|
||||
.addParameter("start_date", startDate.format(DateTimeFormatter.ISO_DATE_TIME))
|
||||
.addParameter("end_date", endDate.format(DateTimeFormatter.ISO_DATE_TIME))
|
||||
.addParameter("start_date", startDate.format(_dateTimeFormat))
|
||||
.addParameter("end_date", endDate.format(_dateTimeFormat))
|
||||
.addParameter("version", replayVersion);
|
||||
|
||||
query.executeUpdate();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.gempukku.lotro.game;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.gempukku.lotro.common.AppConfig;
|
||||
import com.gempukku.lotro.common.DBDefs;
|
||||
import com.gempukku.lotro.db.PlayerDAO;
|
||||
@@ -114,6 +115,16 @@ public class GameRecorder {
|
||||
return new File(playerReplayFolder, gameId + ".xml.gz");
|
||||
}
|
||||
|
||||
private File getSummaryFile(DBDefs.GameHistory history) {
|
||||
var gameReplayFolder = new File(AppConfig.getProperty("application.root"), "replay");
|
||||
var summaryFolder = new File(gameReplayFolder, "summaries");
|
||||
var yearFolder = new File(summaryFolder, String.format("%04d", history.start_date.getYear()));
|
||||
var monthFolder = new File(yearFolder, String.format("%02d", history.start_date.getMonthValue()));
|
||||
monthFolder.mkdirs();
|
||||
return new File(monthFolder, history.winner + "_vs_" + history.loser + "_" +
|
||||
history.win_recording_id + "_" + history.lose_recording_id+ ".json");
|
||||
}
|
||||
|
||||
private OutputStream getRecordingWriteStream(String playerId, String gameId, ZonedDateTime startDate) throws IOException {
|
||||
File recordingFile = getRecordingFileVersion1(playerId, gameId, startDate);
|
||||
recordingFile.getParentFile().mkdirs();
|
||||
@@ -124,6 +135,8 @@ public class GameRecorder {
|
||||
|
||||
private Map<String, String> saveRecordedChannels(Map<String, GameCommunicationChannel> gameProgress, DBDefs.GameHistory gameInfo, Map<String, LotroDeck> decks) {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
var metadata = new ReplayMetadata(gameInfo, decks);
|
||||
|
||||
for (Map.Entry<String, GameCommunicationChannel> playerRecordings : gameProgress.entrySet()) {
|
||||
String playerId = playerRecordings.getKey();
|
||||
String recordingId = "";
|
||||
@@ -135,6 +148,7 @@ public class GameRecorder {
|
||||
}
|
||||
|
||||
final List<GameEvent> gameEvents = playerRecordings.getValue().consumeGameEvents();
|
||||
metadata.ParseReplay(playerId, gameEvents);
|
||||
|
||||
try {
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
@@ -187,10 +201,15 @@ public class GameRecorder {
|
||||
Transformer xformer = TransformerFactory.newInstance().newTransformer();
|
||||
xformer.transform(source, streamResult);
|
||||
}
|
||||
result.put(playerId, recordingId);
|
||||
|
||||
try(var out = new PrintWriter(getSummaryFile(gameInfo).getAbsolutePath())) {
|
||||
out.println(JSON.toJSONString(metadata));
|
||||
}
|
||||
} catch (Exception exp) {
|
||||
|
||||
}
|
||||
result.put(playerId, recordingId);
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
package com.gempukku.lotro.game;
|
||||
|
||||
import com.gempukku.lotro.common.DBDefs;
|
||||
import com.gempukku.lotro.common.Zone;
|
||||
import com.gempukku.lotro.game.state.GameEvent;
|
||||
import com.gempukku.lotro.logic.vo.LotroDeck;
|
||||
import com.mysql.cj.util.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ReplayMetadata {
|
||||
|
||||
public class DeckMetadata {
|
||||
public String Owner;
|
||||
public String TargetFormat;
|
||||
public String DeckName;
|
||||
public List<String> AdventureDeck;
|
||||
public List<String> DrawDeck;
|
||||
public String RingBearer;
|
||||
public String Ring;
|
||||
public List<String> StartingFellowship = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Integer MetadataVersion = 1;
|
||||
|
||||
public DBDefs.GameHistory GameReplayInfo;
|
||||
|
||||
public Map<String, DeckMetadata> Decks = new HashMap<>();
|
||||
public Map<String, Integer> PlayerIDs = new HashMap<>();
|
||||
public Map<String, Integer> Bids = new HashMap<>();
|
||||
public String WentFirst;
|
||||
public boolean GameStarted = false;
|
||||
public boolean Conceded = false;
|
||||
public boolean Canceled = false;
|
||||
|
||||
public Map<String, String> AllCards = new HashMap<>();
|
||||
|
||||
public Set<Integer> SeenCards = new HashSet<>();
|
||||
|
||||
public HashSet<Integer> PlayedCards = new HashSet<>();
|
||||
|
||||
public ReplayMetadata(DBDefs.GameHistory game, Map<String, LotroDeck> decks) {
|
||||
GameReplayInfo = game;
|
||||
|
||||
for(var pair : decks.entrySet()) {
|
||||
String player = pair.getKey();
|
||||
var deck = pair.getValue();
|
||||
var metadata = new DeckMetadata() {{
|
||||
Owner = player;
|
||||
TargetFormat = deck.getTargetFormat();
|
||||
DeckName = deck.getDeckName();
|
||||
AdventureDeck = deck.getSites();
|
||||
DrawDeck = deck.getAdventureCards();
|
||||
RingBearer = deck.getRingBearer();
|
||||
Ring = deck.getRing();
|
||||
}};
|
||||
|
||||
Decks.put(player, metadata);
|
||||
}
|
||||
|
||||
if(GameReplayInfo.lose_reason.contains("cancelled") || GameReplayInfo.win_reason.contains("cancelled")) {
|
||||
Canceled = true;
|
||||
}
|
||||
|
||||
if(GameReplayInfo.lose_reason.contains("Concession") || GameReplayInfo.win_reason.contains("Concession")) {
|
||||
Conceded = true;
|
||||
}
|
||||
}
|
||||
|
||||
public String GetOpponent(String player) {
|
||||
return PlayerIDs.keySet().stream().filter(x -> !x.equals(player)).findFirst().get();
|
||||
}
|
||||
|
||||
private final Pattern gameStartPattern = Pattern.compile("Players in the game are: ([\\w-]+), ([\\w-]+)");
|
||||
private final Pattern orderPattern = Pattern.compile("([\\w-]+) has chosen to go (.*)");
|
||||
private final Pattern bidPattern = Pattern.compile("([\\w-]+) bid (\\d+)");
|
||||
public void ParseReplay(String player, List<GameEvent> events) {
|
||||
GameStarted = false;
|
||||
|
||||
for(var event : events) {
|
||||
if(event.getType() == GameEvent.Type.SEND_MESSAGE) {
|
||||
var message = event.getMessage();
|
||||
if(StringUtils.isNullOrEmpty(message))
|
||||
continue;
|
||||
|
||||
var regex = gameStartPattern.matcher(message);
|
||||
if(regex.matches()) {
|
||||
PlayerIDs.put(regex.group(1), 1);
|
||||
PlayerIDs.put(regex.group(2), 2);
|
||||
continue;
|
||||
}
|
||||
|
||||
regex = orderPattern.matcher(message);
|
||||
if(regex.matches()) {
|
||||
String bidder = regex.group(1);
|
||||
String order = regex.group(2);
|
||||
if(order.equals("first")) {
|
||||
WentFirst = bidder;
|
||||
}
|
||||
else if(order.equals("second")) {
|
||||
WentFirst = GetOpponent(bidder);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
regex = bidPattern.matcher(message);
|
||||
if(regex.matches()) {
|
||||
String bidder = regex.group(1);
|
||||
String bid = regex.group(2);
|
||||
Bids.put(bidder, Integer.valueOf(bid));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if(!GameStarted && event.getType() == GameEvent.Type.GAME_PHASE_CHANGE) {
|
||||
var phase = event.getPhase();
|
||||
if (phase != null && phase.equals("Between turns"))
|
||||
{
|
||||
GameStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
else if(event.getType() == GameEvent.Type.PUT_CARD_INTO_PLAY) {
|
||||
|
||||
var bpID = event.getBlueprintId();
|
||||
var cardID = event.getCardId();
|
||||
var participantID = event.getParticipantId();
|
||||
var zone = event.getZone();
|
||||
var targetCardID = event.getTargetCardId();
|
||||
|
||||
if (bpID != null && cardID != null && participantID != null && participantID.equals(player)) {
|
||||
if (!GameStarted && (zone.equals(Zone.FREE_CHARACTERS)) || zone.equals(Zone.ATTACHED)) {
|
||||
Decks.get(player).StartingFellowship.add(bpID);
|
||||
}
|
||||
|
||||
switch (zone) {
|
||||
case FREE_CHARACTERS, SUPPORT, SHADOW_CHARACTERS, ADVENTURE_PATH, VOID_FROM_HAND, VOID -> {
|
||||
AllCards.put(cardID.toString(), bpID);
|
||||
SeenCards.add(cardID);
|
||||
PlayedCards.add(cardID);
|
||||
}
|
||||
case ATTACHED, HAND, STACKED, DEAD, DISCARD, ADVENTURE_DECK, DECK, REMOVED -> {
|
||||
AllCards.put(cardID.toString(), bpID);
|
||||
SeenCards.add(cardID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user