com.github.kaisle.util.ReplayRetriever Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of DotA2-Wrapper Show documentation
Show all versions of DotA2-Wrapper Show documentation
A wrapper for the DotA2 WebAPI written in Java.
package com.github.kaisle.util;
import com.github.kaisle.data.ReplayResponse;
import org.apache.commons.io.FileUtils;
import org.eclipse.jetty.util.log.Log;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
/**
* Created by Anders Borum on 03-06-2015.
*/
public class ReplayRetriever {
private final org.slf4j.Logger log = LoggerFactory.getLogger(RuntimeUtil.class.getPackage().getClass());
private int maxAttempts;
private int timeout;
private TimeUnit timeUnit;
/**
* A retriever that fetches replays by using a Steam bot.
* @param maxAttempts The max amount of times the retriever should call the Game Coordinator before terminating. 5 should do in most cases.
* @param timeout The amount of time to wait for a response. 5 seconds should do in most cases.
* @param timeUnit The time unit for the timeout.
*/
public ReplayRetriever(int maxAttempts, int timeout, TimeUnit timeUnit) {
this.maxAttempts = maxAttempts;
this.timeout = timeout;
this.timeUnit = timeUnit;
}
public void getReplay(String matchId) {
//ReplayResponse replayResponse = getReplaySalt(matchId);
}
/**
* Retrieve the replay salt for a given match.
* @param matchId The match id of the match.
*/
public List getReplaySalt(List matchId) {
String workingDir = FileUtil.getWorkingDirectory();
try {
FileUtils.copyInputStreamToFile(this.getClass().getClassLoader().getResourceAsStream("/" + NodeDotaDefines.execution_file_name), new File(workingDir + "/" + NodeDotaDefines.execution_file_name));
FileUtils.copyInputStreamToFile(this.getClass().getClassLoader().getResourceAsStream("/" + NodeDotaDefines.config_file_name), new File(workingDir + "/" + NodeDotaDefines.config_file_name));
FileUtils.copyInputStreamToFile(this.getClass().getClassLoader().getResourceAsStream("/" + "sentry"), new File(workingDir + "/" + "sentry"));
FileUtils.copyInputStreamToFile(this.getClass().getClassLoader().getResourceAsStream("/" + "servers"), new File(workingDir + "/" + "servers"));
} catch (IOException e) {
e.printStackTrace();
}
//NumberUtil.evaluateString(matchId);
String[] commands = {"node", NodeDotaDefines.execution_file_name};
File directory = new File(workingDir);
log.info("Adding requests.");
addMatchDetailsRequests(matchId); // Add requests to node-dota.js.
RuntimeUtil runtimeUtil = new RuntimeUtil();
ProcessBuilder process = runtimeUtil.buildProcess(commands, directory); // Build the process
for (int i = 0; i < maxAttempts; i++) {
List input = runtimeUtil.executeWithTimeout(process, timeout, timeUnit);
if (input.size() < 200) { // The request failed since the console input is not big enough to represent a valid response.
try {
log.info("Request failed, trying again.");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
continue;
}
HashMap values = new HashMap();
List replayResponses = new ArrayList();
for (String inputLine : input) { // Loop through the console input and store the relevant data in a map
if (inputLine.contains("cluster")) {
values.put("cluster", inputLine.substring(15, inputLine.length() - 1));
}
else if (inputLine.contains("matchId")) {
values.put("matchId", inputLine.substring(16, inputLine.length() - 2));
}
else if (inputLine.contains("replaySalt")) {
values.put("replaySalt", inputLine.substring(inputLine.indexOf(":") + 2, inputLine.length() - 1));
}
else if (inputLine.contains("replayState")) {
values.put("replayState", inputLine.substring(inputLine.indexOf(":") + 3, inputLine.length() - 2));
if (values.get("replayState").equals("REPLAY_EXPIRED")) {
replayResponses.add(new ReplayResponse(values.get("replaySalt"), false, values.get("cluster"), values.get("matchId"))); // Reached end of response, build new object containing the data
}
else if (values.get("replayState").equals("REPLAY_AVAILABLE")) {
replayResponses.add(new ReplayResponse(values.get("replaySalt"), true, values.get("cluster"), values.get("matchId")));
}
}
}
File nodeDota = new File(workingDir + "/" + NodeDotaDefines.execution_file_name);
FileUtil.removeLines(nodeDota, "Dota2.matchDetailsRequest"); // Clean up file
return replayResponses;
}
return null;
}
/**
* Add a single matchdetails request to the node-dota.js file.
* @param matchId
*/
public void addMatchDetailsRequest(String matchId) {
String workingDir = FileUtil.getWorkingDirectory();
File nodeDota = new File(workingDir + "/" + NodeDotaDefines.execution_file_name);
String requestLine = " " + NodeDotaDefines.match_details_request + "(" + matchId + ");";
FileUtil.modifyLine(nodeDota, requestLine, NodeDotaDefines.match_details_request_line_number);
}
/**
* Add several matchdetails requests to the node-dota.js file.
* @param matchIds
*/
public void addMatchDetailsRequests(List matchIds) {
String workingDir = FileUtil.getWorkingDirectory();
File nodeDota = new File(workingDir + "/" + NodeDotaDefines.execution_file_name);
List inputLines = new ArrayList();
for (String matchId: matchIds) {
inputLines.add(" " + NodeDotaDefines.match_details_request + "(" + matchId + ");");
}
FileUtil.appendLinesToMiddle(nodeDota, inputLines, NodeDotaDefines.match_details_request_line_number);
}
public void getReplay(String path, ReplayResponse replayResponse) {
String urlString = "http://replay" + replayResponse.getCluster() + ".valve.net/570/" + replayResponse.getReplaySalt() + "_" + replayResponse.getMatch_id() + ".dem.bz2";
try {
URL url = new URL(urlString);
HttpURLConnection con = (HttpURLConnection) (url).openConnection();
con.connect();
FileUtils.copyInputStreamToFile(con.getInputStream(), new File(path));
con.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}