Initial commit

This commit is contained in:
KoalaTrapLord committed 2026-03-10 12:13:56 -04:00
commit e6b5e0cedb
402 files changed
+64931

No files matched your search

@@ -0,0 +1,159 @@
package commanderailab.bridge;
import commanderailab.schema.BatchResult;
import commanderailab.schema.BatchResult.*;
import commanderailab.schema.JsonExporter;
import commanderailab.stats.StatsAggregator;
import commanderailab.ai.AiPolicy;
import commanderailab.ai.ForgeBuiltinPolicy;
import commanderailab.batch.BatchRunner;
import commanderailab.batch.MultiThreadBatchRunner;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.time.Instant;
import java.util.*;
/**
* WebApiBridge — HTTP/WebSocket API layer for the web UI.
*
* This class provides methods that can be called from a web server
* (e.g., Javalin, Spring, or the existing Python FastAPI server)
* to trigger batch runs and retrieve results.
*/
public class WebApiBridge {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private final String forgeJarPath;
private final String forgeWorkDir;
private volatile BatchResult lastResult;
private volatile boolean isRunning;
private volatile int progress;
private String policyServerUrl = "http://localhost:8080";
public WebApiBridge(String forgeJarPath, String forgeWorkDir) {
this.forgeJarPath = forgeJarPath;
this.forgeWorkDir = forgeWorkDir;
this.isRunning = false;
this.progress = 0;
}
/**
* Start a batch run (backward-compatible, Forge AI only).
*/
public String startBatchAsync(String deck1, String deck2, String deck3,
int numGames, int threads, Long seed) {
return startBatchAsync(deck1, deck2, deck3, numGames, threads, seed, false, "midrange");
}
/**
* Start a batch with learned policy support.
*
* @param useLearnedPolicy If true, attempts to use the trained neural network policy
* @param policyStyle Playstyle for the learned policy ("aggro", "control", "midrange", "combo")
*/
public String startBatchAsync(String deck1, String deck2, String deck3,
int numGames, int threads, Long seed,
boolean useLearnedPolicy, String policyStyle) {
String batchId = UUID.randomUUID().toString();
Thread batchThread = new Thread(() -> {
try {
isRunning = true;
progress = 0;
List<DeckInfo> decks = buildDecks(deck1, deck2, deck3);
AiPolicy policy;
if (useLearnedPolicy) {
commanderailab.ml.LearnedPolicy learned =
new commanderailab.ml.LearnedPolicy(
policyServerUrl,
policyStyle != null ? policyStyle : "midrange",
true
);
if (learned.connect()) {
policy = learned;
System.out.println("[ML] Using learned policy for batch " + batchId);
} else {
System.out.println("[ML] Learned policy unavailable, using Forge AI");
policy = new ForgeBuiltinPolicy();
}
} else {
policy = new ForgeBuiltinPolicy();
}
long startTime = System.currentTimeMillis();
List<GameResult> games;
if (threads > 1) {
MultiThreadBatchRunner runner = new MultiThreadBatchRunner(
forgeJarPath, forgeWorkDir, decks, policy, threads);
games = runner.runBatch(numGames, seed);
} else {
BatchRunner runner = new BatchRunner(
forgeJarPath, forgeWorkDir, decks, policy);
games = runner.runBatchSingleThread(numGames, seed);
}
long elapsed = System.currentTimeMillis() - startTime;
Summary summary = StatsAggregator.computeSummary(games, decks, elapsed);
BatchResult result = new BatchResult();
result.metadata = new Metadata();
result.metadata.batchId = batchId;
result.metadata.timestamp = Instant.now().toString();
result.metadata.totalGames = numGames;
result.metadata.completedGames = games.size();
result.metadata.engineVersion = "forge-2.0.12-SNAPSHOT";
result.metadata.masterSeed = seed;
result.metadata.threads = threads;
result.metadata.elapsedMs = elapsed;
result.decks = decks;
result.games = games;
result.summary = summary;
lastResult = result;
progress = 100;
} catch (Exception e) {
System.err.println("Batch run failed: " + e.getMessage());
e.printStackTrace();
} finally {
isRunning = false;
}
}, "batch-runner-" + batchId);
batchThread.setDaemon(true);
batchThread.start();
return batchId;
}
public int getProgress() { return progress; }
public boolean isRunning() { return isRunning; }
public String getLastResultJson() {
if (lastResult == null) return "{}";
return JsonExporter.toJson(lastResult);
}
public BatchResult getLastResult() { return lastResult; }
private List<DeckInfo> buildDecks(String... deckNames) {
List<DeckInfo> decks = new ArrayList<>();
for (int i = 0; i < deckNames.length; i++) {
DeckInfo d = new DeckInfo();
d.seatIndex = i;
d.deckFile = deckNames[i];
d.deckName = deckNames[i].replace(".dck", "");
d.commanderName = d.deckName;
d.colorIdentity = List.of();
d.cardCount = 100;
decks.add(d);
}
return decks;
}
}