Skip to content

Commit

Permalink
Add support for Deck and Okay JSON messages
Browse files Browse the repository at this point in the history
 - Deck messages simply contain the decklist

 - Okay messages are now necessary since the backend is now messaged only when tips or cards
   have changed, not every second. The pubsub broadcast frequency is now managed by the backend.
   Therefore an Okay message is a way to tell backend that the game is still running.
   It is being sent once a second

 - Messages can now be sent to the backend much more often than 1/sec

 - Uses a separate broadcaster for each of the 3 message types with a separate thread

 - Added JSONMessageBuilder as a parent class to both TipsJSONBuilder and DeckJSONBuilder
   TipsJSONBuilder is now what JSONMessageBuilder used to be
  • Loading branch information
avolny committed Apr 18, 2020
1 parent f8e69d5 commit a95f89e
Show file tree
Hide file tree
Showing 5 changed files with 844 additions and 813 deletions.
258 changes: 124 additions & 134 deletions src/main/java/str_exporter/BackendBroadcaster.java
Original file line number Diff line number Diff line change
@@ -1,134 +1,124 @@
package str_exporter;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.locks.ReentrantLock;

public class BackendBroadcaster {

public static final Logger logger = LogManager.getLogger(BackendBroadcaster.class.getName());

// private static final String EBS_URL = "https://localhost:8081";
private static final String EBS_URL = "https://slaytherelics.xyz:8081";

private static final long CHECK_QUEUE_PERIOD_MILLIS = 100;
private static BackendBroadcaster instance = new BackendBroadcaster();

private String message;
private long messageTimestamp;
private ReentrantLock queueLock;
private Thread worker;

private BackendBroadcaster() {
message = null;
queueLock = new ReentrantLock();

worker = new Thread(() -> {
while (true) {
readQueue();

try {
Thread.sleep(CHECK_QUEUE_PERIOD_MILLIS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}

public static void start() {
instance.worker.start();
}

public static void queueMessage(String msg) {
instance.queueLock.lock();
try {
if (instance.message == null || !instance.message.equals(msg)) {
instance.message = msg;
instance.messageTimestamp = System.currentTimeMillis();
}
} finally {
instance.queueLock.unlock();
}
}

private void readQueue() {
String msg = "";
long ts = 0;
queueLock.lock();
try {
if (message != null) {
msg = message;
ts = messageTimestamp;
message = null;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
queueLock.unlock();
if (!msg.isEmpty()) {
broadcastMessage(msg, ts);

try {
Thread.sleep(950);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

private static String injectDelayToMessage(String msg, long delay) {
return "{\"d\":" + delay + "," + msg.substring(1);
}

private static String compressPowerTips(String msg) {
int index = msg.lastIndexOf("\"w\":\"");

String comp_powertips = StringCompression.compress(msg.substring(index + 5, msg.length() - 3));
return msg.substring(0, index + 5) + comp_powertips + "\"}}";
}

private void broadcastMessage(String msg, long msgTimestamp) {

try {
URL url = new URL(EBS_URL);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json"); //; utf-8
con.setRequestProperty("Accept", "application/json");
con.setDoOutput(true);

msg = compressPowerTips(msg);
long msgDelay = msgTimestamp - System.currentTimeMillis() + SlayTheRelicsExporter.delay;
msg = injectDelayToMessage(msg, msgDelay);

OutputStream os = con.getOutputStream();
byte[] input = msg.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);

BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8));
StringBuilder response = new StringBuilder();
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}

if (!response.toString().equals("Success"))
logger.info("message not broadcasted succesfully, response: " + response.toString());
// logger.info("broadcasted message, response: " + response.toString());

} catch (Exception e) {
e.printStackTrace();
} finally {
// logger.info(SlayTheRelicsExporter.removeSecret(msg));
}
}
}
package str_exporter;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.locks.ReentrantLock;

public class BackendBroadcaster {

public static final Logger logger = LogManager.getLogger(BackendBroadcaster.class.getName());

// private static final String EBS_URL = "https://localhost:8081";
private static final String EBS_URL = "https://slaytherelics.xyz:8081";

// private static final long CHECK_QUEUE_PERIOD_MILLIS = 100;
// private static BackendBroadcaster instance = new BackendBroadcaster();

public static final String DELAY_PLACEHOLDER = "&&&DELAY&&&";

private String message;
private String lastMessage;
private long messageTimestamp;
private ReentrantLock queueLock;
private Thread worker;
private long checkQueuePeriodMillis;

public BackendBroadcaster(long checkQueuePeriodMillis) {
this.checkQueuePeriodMillis = checkQueuePeriodMillis;
message = null;
lastMessage = null;
queueLock = new ReentrantLock();

worker = new Thread(() -> {
while (true) {
readQueue();

try {
Thread.sleep(checkQueuePeriodMillis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});

worker.start();
}

public void queueMessage(String msg) {
queueLock.lock();
try {
if (message == null || !message.equals(msg)) {
message = msg;
messageTimestamp = System.currentTimeMillis();
}
} finally {
queueLock.unlock();
}
}

private void readQueue() {
String msg = "";
long ts = 0;
queueLock.lock();
try {
if (message != null && !message.equals(lastMessage)) {
lastMessage = message;
msg = message;
ts = messageTimestamp;
message = null;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
queueLock.unlock();
if (!msg.isEmpty()) {
long msgDelay = ts - System.currentTimeMillis() + SlayTheRelicsExporter.delay;
msg = injectDelayToMessage(msg, msgDelay);
broadcastMessage(msg);
}
}
}

private static String injectDelayToMessage(String msg, long delay) {
return msg.replace(DELAY_PLACEHOLDER, Long.toString(delay));
}

public void broadcastMessage(String msg) {

try {
URL url = new URL(EBS_URL);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/json"); //; utf-8
con.setRequestProperty("Accept", "application/json");
con.setDoOutput(true);

OutputStream os = con.getOutputStream();
byte[] input = msg.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);

BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8));
StringBuilder response = new StringBuilder();
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}

if (!response.toString().equals("Success"))
logger.info("message not broadcasted succesfully, response: " + response.toString());
// logger.info("broadcasted message, response: " + response.toString());

} catch (Exception e) {
e.printStackTrace();
} finally {
// logger.info(SlayTheRelicsExporter.removeSecret(msg));
}
}
}
Loading

0 comments on commit a95f89e

Please sign in to comment.