package nl.tudelft.bw4t.scenariogui.util;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.JAXBException;
import nl.tudelft.bw4t.map.EntityType;
import nl.tudelft.bw4t.scenariogui.BW4TClientConfig;
import nl.tudelft.bw4t.scenariogui.BotConfig;
import nl.tudelft.bw4t.scenariogui.EPartnerConfig;
import nl.tudelft.bw4t.scenariogui.ScenarioEditor;
import nl.tudelft.bw4t.util.FileUtils;
/**
* Loads the BW4TClientConfiguration and exports it as a mas2g file, creating
* all the necessary files.
*/
public final class ExportToMAS {
private static final String TAB = "\t";
private static final String NEWLINE = "\n";
private static final String ENVIRONMENT = "env = \"BW4T3/BW4TClient.jar\" ."
+ NEWLINE;
private static final String INIT = "init = [ "
+ "configfile = \"%s.xml\" ] ." + NEWLINE;
private static String init = "";
private static BW4TClientConfig configuration;
private static String directory;
private static File mas2gFile;
private static int agentCount;
private static int humanCount;
private static StringBuilder launchPolicyBuilder;
private static Map<String, String> goalFiles;
/** Prevents this class from being instantiated. */
private ExportToMAS() {
}
/**
* Generates a GOAL configuration in the specified directory from the
* BW4TClientConfig given.
*
* @param directory
* The directory where the configuration has to be stored.
* @param configuration
* The BW4TClientConfig to be generated.
*/
public static void export(String directory, BW4TClientConfig configuration,
String configurationName) {
ExportToMAS.directory = directory;
ExportToMAS.configuration = configuration;
goalFiles = new HashMap<String, String>();
init = String
.format(INIT, new File(directory + "/" + configurationName).getAbsolutePath());
agentCount = 0;
humanCount = 0;
try {
generateMASFile(configurationName);
} catch (IOException ex) {
ScenarioEditor.handleException(ex,
"An IO Exception has occurred. Please try again.");
} catch (JAXBException ex) {
ScenarioEditor.handleException(ex,
"A problem occured while attempting to export the protect. "
+ "Please try again.");
}
}
private static void generateMASFile(String configurationName)
throws IOException, FileNotFoundException, JAXBException {
generateHierarchy(configurationName);
buildLaunchPolicy();
generateEnvironmentBlock();
generateAgentBlock();
generateLaunchPolicy();
// Save the configuration again with the latest changes concerning
// the goal files.
configuration.setFileLocation(directory + "/" + configurationName
+ ".xml");
configuration.toXML();
}
private static void generateHierarchy(String configurationName)
throws IOException {
File directory = new File(ExportToMAS.directory);
directory.mkdir();
/* Create the agents directory. */
File agentFolder = new File(directory.getAbsolutePath() + "/agents/");
agentFolder.mkdir();
/* And the mas2g file, since it will be overwritten in every case. */
ExportToMAS.mas2gFile = new File(directory.getAbsolutePath() + "/"
+ configurationName + ".mas2g");
mas2gFile.delete();
mas2gFile.createNewFile();
generateAgentHierarchy(directory);
}
private static void generateAgentHierarchy(File directory)
throws IOException {
generateAgentHierarchyForBots(directory);
generateAgentHierarchyForEPartners(directory);
}
private static void generateAgentHierarchyForBots(File directory) {
for (BotConfig bot : ExportToMAS.configuration.getBots()) {
String botGoalFilename = bot.getFileName();
File goalFile = new File(botGoalFilename);
if (goalFile.exists()) {
/*
* Case 1: Existing GOAL file Check if the filename doesn't
* already exist, if so do nothing.
*/
String goalFilename = goalFile.getName();
File goalFileInDirectory = new File(directory.getAbsolutePath()
+ "/agents/" + goalFilename);
if (!goalFileInDirectory.exists()) {
FileUtils.copyFile(goalFile, goalFileInDirectory);
}
// Set the filename to the copied one.
bot.setFileName(goalFilename);
}
}
}
private static void generateAgentHierarchyForEPartners(File directory) {
/*
* Loop through the bots, and create the files.
* File.createNewFile only creates a file if it does not yet exist, so
* no checks are needed.
*/
for (EPartnerConfig epartner : ExportToMAS.configuration.getEpartners()) {
String epartnerFileName = epartner.getFileName();
File goalFile = new File(epartnerFileName);
if (goalFile.exists()) {
String goalFileName = goalFile.getName();
File goalFileInDirectory = new File(directory.getAbsolutePath()
+ "/agents/" + goalFileName);
if (!goalFileInDirectory.exists()) {
FileUtils.copyFile(goalFile, goalFileInDirectory);
}
epartner.setFileName(goalFileName);
}
}
}
private static void buildLaunchPolicy() {
launchPolicyBuilder = new StringBuilder();
buildBotLaunchPolicy();
buildEPartnerLaunchPolicy();
}
private static void buildBotLaunchPolicy() {
for (BotConfig bot : configuration.getBots()) {
boolean isHuman = bot.getBotController() == EntityType.HUMAN;
String type = isHuman ? "human" : "bot";
if (!isHuman) {
agentCount += bot.getBotAmount();
} else {
humanCount += bot.getBotAmount();
}
launchPolicyBuilder.append(TAB);
launchPolicyBuilder.append(String.format("when [type=%s,max=%d]@env do launch %s: %s .",
type,
Integer.valueOf(bot.getBotAmount()),
bot.getBotName().toLowerCase().replace(" ", "_"),
bot.getReferenceName()));
launchPolicyBuilder.append(NEWLINE);
/* Remove the last 5 characters since that is the extension. */
goalFiles.put(bot.getFileName(), bot.getReferenceName());
}
}
private static void buildEPartnerLaunchPolicy() {
for (EPartnerConfig epartner : configuration.getEpartners()) {
agentCount += epartner.getEpartnerAmount();
launchPolicyBuilder.append(TAB);
launchPolicyBuilder.append(String.format(
"when [type=%s,max=%d]@env do launch %s: %s .",
"epartner", Integer.valueOf(epartner.getEpartnerAmount()),
epartner.getEpartnerName().toLowerCase().replace(" ", "_"),
epartner.getReferenceName()));
launchPolicyBuilder.append(NEWLINE);
goalFiles.put(epartner.getFileName(), epartner.getReferenceName());
}
}
private static void generateEnvironmentBlock() throws IOException {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(
ExportToMAS.mas2gFile, true)));
out.println("environment{");
out.print(TAB);
out.print(ENVIRONMENT);
String initField = String.format(init, configuration.getClientIp(),
configuration.getClientPort(), configuration.getServerIp(),
configuration.getServerPort(), agentCount, humanCount,
configuration.isLaunchGui() ? "true" : "false");
out.print(TAB);
out.print(initField);
out.println("}");
out.close();
}
private static void generateAgentBlock() throws IOException {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(
ExportToMAS.mas2gFile, true)));
out.println();
out.println("agentfiles{");
for (Map.Entry<String, String> item : goalFiles.entrySet()) {
String entry = TAB + "\"agents/%s\" [name = %s] ." + NEWLINE;
out.append(String.format(entry, item.getKey(), item.getValue()));
}
out.println("}");
out.close();
}
private static void generateLaunchPolicy() throws IOException {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(
ExportToMAS.mas2gFile, true)));
out.println();
out.println("launchpolicy{");
out.print(launchPolicyBuilder);
out.println("}");
out.close();
}
}