package AIRunner.Implementation;
import AIRunner.Interface.IAIRunnerEventHandler;
import AgentSystemManagement.Interface.IAgentSystemManagement;
import AgentSystemPluginAPI.Contract.IAgentSystem;
import AgentSystemPluginAPI.Contract.TAgentSystemDescription;
import EnvironmentPluginAPI.Contract.IEnvironmentState;
import EnvironmentPluginAPI.Exceptions.TechnicalException;
import EnvironmentPluginAPI.Service.IEnvironmentConfiguration;
import NetworkAdapter.Interface.Exceptions.ConnectionLostException;
import NetworkAdapter.Interface.Exceptions.HostUnreachableException;
import NetworkAdapter.Interface.Exceptions.NotConnectedException;
import NetworkAdapter.Interface.IClientNetworkAdapter;
import NetworkAdapter.Interface.MessageChannel;
import PluginLoader.Interface.Exceptions.PluginNotReadableException;
import PluginLoader.Interface.IAgentSystemPluginLoader;
import ZeroTypes.Settings.SettingException;
/**
* This class implements the logic of the periodic receiving and sending of game related messages and feeding the
* plugin with it.
*/
public class PluginContainer extends Thread {
// ------------------------------ FIELDS ------------------------------
private final IAgentSystemManagement agentSystemManagement;
private final IClientNetworkAdapter clientNetworkAdapter;
private final IAIRunnerEventHandler IAIRunnerEventHandler;
private final IAgentSystemPluginLoader agentSystemPluginLoader;
private IAgentSystem plugin;
private IEnvironmentState environmentState;
private TAgentSystemDescription agentSystemDescription;
private String hostname;
private int port;
// --------------------------- CONSTRUCTORS ---------------------------
public PluginContainer(IAgentSystemManagement agentSystemManagement,
IClientNetworkAdapter clientNetworkAdapter,
IAIRunnerEventHandler aiRunnerEventHandler,
IAgentSystemPluginLoader agentSystemPluginLoader, String hostname, int port)
throws TechnicalException, PluginNotReadableException {
this.agentSystemManagement = agentSystemManagement;
this.clientNetworkAdapter = clientNetworkAdapter;
this.IAIRunnerEventHandler = aiRunnerEventHandler;
this.agentSystemPluginLoader = agentSystemPluginLoader;
this.hostname = hostname;
this.port = port;
environmentState = null;
}
// ------------------------ INTERFACE METHODS ------------------------
// --------------------- Interface Runnable ---------------------
@Override
public void run() {
//try to connect to the server, if not possible exit
try {
plugin = agentSystemManagement.getAgentSystem(agentSystemDescription);
clientNetworkAdapter.connectToServer(hostname, port, agentSystemDescription.toString());
Thread.currentThread().setContextClassLoader(agentSystemPluginLoader.getUsedClassLoader());
} catch (TechnicalException e) {
handleException(e);
return;
} catch (PluginNotReadableException e) {
handleException(e);
return;
} catch (SettingException e) {
handleException(e);
return;
} catch (HostUnreachableException e) {
handleException(e);
return;
}
/*
* Wait for environment states to be received.
* When it is received, get according action from agent system plugin, send it to the server
*/
while (!isInterrupted()) {
try {
synchronized (this) { // make sure that the value of environmentState doesn't change during this section
if (!isInterrupted() && environmentState != null) {
clientNetworkAdapter.sendNetworkMessage(
agentSystemPluginLoader.createActionDescriptionMessage(clientNetworkAdapter.getClientId(),
plugin.getActionsForEnvironmentStatus(environmentState))
, MessageChannel.DATA);
environmentState = null;
} else {
wait(150); // after a
}
}
} catch (InterruptedException e) {
handleException(e);
} catch (ConnectionLostException e) {
handleException(e);
} catch (NotConnectedException e) {
handleException(e);
} catch (TechnicalException e) {
handleException(e);
}
}
}
// -------------------------- PUBLIC METHODS --------------------------
public void end() {
try {
plugin.end();
} catch (TechnicalException e) {
handleException(e);
}
}
/**
* Loads the plugin and starts running the session
*
* @param agentSystemDescription the plugin's description != null
*/
public void load(TAgentSystemDescription agentSystemDescription) {
this.agentSystemDescription = agentSystemDescription;
start();
}
/**
* memorizes the environmentState for processing upon waking up
*
* @param environmentState
*/
public void receiveGameState(IEnvironmentState environmentState) {
synchronized (this) {
this.environmentState = environmentState;
notify();
}
}
public void start(IEnvironmentConfiguration environmentConfiguration) {
try {
plugin.start(environmentConfiguration);
} catch (TechnicalException e) {
handleException(e);
}
}
private void handleException(Exception e) {
interrupt();
IAIRunnerEventHandler.onException(e);
plugin = null;
}
/**
* interrupts this thread.
*/
public void stopPlugin() {
interrupt();
plugin = null;
}
}