Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
5.8 kB · 146 lines
Java
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147package TemplateCompiler;
import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.OutputStream;import java.lang.reflect.Field;import java.net.HttpURLConnection;import java.net.URL;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Set;import java.util.StringTokenizer;
/** * Asks the jev-facade sidecar which discourse acts a typed line is. * * This runs on the game's bundled Java 1.4.2, so it sticks to 1.4 APIs: no * StringBuilder, no generics, no connection timeout setters (the * sun.net.client.* properties below are the 1.4 way to bound a request). */public final class JevBridge { private static final String ENDPOINT = System.getProperty("facadejev.url", "http://127.0.0.1:8765/da"); private static final int VALUES_PER_ACT = 5; private static final long RETRY_AFTER_MS = 15000L; /** Only the NLU thread calls classify, so this needs no locking. */ private static long skipUntil = 0L;
static { System.setProperty("sun.net.client.defaultConnectTimeout", "1500"); System.setProperty("sun.net.client.defaultReadTimeout", "5000"); }
private JevBridge() { }
/** * Returns one int[5] per act (type, character, param1, param2, param3), or * null when the sidecar could not answer and the caller should fall back. */ public static int[][] classify(String text) { if (System.currentTimeMillis() < skipUntil) { return null; } HttpURLConnection connection = null; try { connection = (HttpURLConnection) new URL(ENDPOINT).openConnection(); connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "text/plain; charset=utf-8"); OutputStream out = connection.getOutputStream(); out.write(buildRequest(text).getBytes("UTF-8")); out.close(); int status = connection.getResponseCode(); if (status != 200) { // The sidecar is up but Jev is not; it answers at once, so no backoff. System.out.println(new StringBuffer("jev-facade: sidecar answered ").append(status) .append(", using the original parser").toString()); return null; } BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); List acts = new ArrayList(); String line; while ((line = reader.readLine()) != null) { int[] act = parseAct(line); if (act != null) { acts.add(act); } } reader.close(); if (acts.isEmpty()) { return null; } return (int[][]) acts.toArray(new int[acts.size()][]); } catch (Exception failure) { // A refused connection costs up to the connect timeout on Windows, // so stop paying it on every line while the sidecar is down. skipUntil = System.currentTimeMillis() + RETRY_AFTER_MS; // No string "+" anywhere in this patch: javac turns it into // StringBuilder, which does not exist on Java 1.4. System.out.println(new StringBuffer("jev-facade: sidecar unavailable, using the original parser: ") .append(failure).toString()); return null; } finally { if (connection != null) { connection.disconnect(); } } }
static String buildRequest(String text) { StringBuffer body = new StringBuffer(); body.append("text\t").append(oneLine(text)).append('\n'); Iterator contexts = activeContexts().iterator(); while (contexts.hasNext()) { body.append("context\t").append(oneLine(String.valueOf(contexts.next()))).append('\n'); } // Script identifiers of what Trip and Grace just said; the sidecar // turns them into readable lines. Iterator said = JevDialogueLog.recent().iterator(); while (said.hasNext()) { body.append("said\t").append(oneLine(String.valueOf(said.next()))).append('\n'); } return body.toString(); }
static int[] parseAct(String line) { StringTokenizer tokens = new StringTokenizer(line); if (tokens.countTokens() != VALUES_PER_ACT) { return null; } int[] act = new int[VALUES_PER_ACT]; try { for (int i = 0; i < VALUES_PER_ACT; i++) { act[i] = Integer.parseInt(tokens.nextToken()); } } catch (NumberFormatException malformed) { return null; } return act; }
private static String oneLine(String value) { return value.replace('\n', ' ').replace('\r', ' ').replace('\t', ' '); }
/** * NLUMain keeps what the couple is listening for in a private static set, * changed only through its static synchronized activate/deactivateContext * methods, which lock the NLUMain class; so that is the lock to copy under. */ private static List activeContexts() { List copy = new ArrayList(); try { Class nluMain = Class.forName("TemplateCompiler.NLUMain"); Field field = nluMain.getDeclaredField("activeContexts"); field.setAccessible(true); synchronized (nluMain) { copy.addAll((Set) field.get(null)); } } catch (Throwable unavailable) { // Running outside the game (the test harness): no contexts to send. } return copy; }}