Create a JAR file in eclipse dynamically from the code - java

I am currently working on a TESTING a game project. Below are the details about my project.
This is my first Maven Project and I really have very less idea on it's working methodology.Please help me!
1] GameProject - Is a Maven Project in Eclipse. The main goals of this project is to create a game player (also called bot) for a First Person Shooter game. When you run this Java Application, it will run the game, with a new player, whose actions will be determined by the code I wrote up in this project.
It has lot of java files, and one main class. There is a class called PlayerInfo.Java, which contains the code to decide, what the player should do while playing the game. It is like the brain of the player. Let's say it has around 40 variables, which decides the behavior of the Player.
Example - One of the variable in the class may be like Player_HEALTH_Level = 50. This means that Player should have atleast 50% of the health to be able to fight with other players. If it's less than this, then He/she should find a health Pack and increase the value. Similarly I have few other 39 parameters.
2] Testing Project - This too is a maven Project. Which is designed to test my Player(bot) performance in the game. Such as, how many times he wins the match, number of weapons he collects, etc.
The way this project is designed that, it requires the path for the JAR file of the GameProject as a input in the Main Method. Then, It runs the bot/player for the given JAR and prints out the results of the game in a separate file.
Example -
In the Main Method I specify something like this
String playerJAR_Path = "C:\Users\Player\Netbeans\GameProject-one-SNAPSHOT-jar.jar"
Note:- The above is the path for GameProject JAR folder. Basically, I just build the GameProject as "Maven Install" and it will create a JAR for me. Then use the path address on the second Project.
Hope this gives you some idea about my project structure.
Issue
The real issue is I have to basically run my GameProject around 500 times and capture the results. I am using Genetic Algorithms to evolve the Player Parameters and improve them over the time.
Currently, I can have a for Loop in my TestingProject, to loop 500 Iterations and it takes cares of executing the GameProject 500 times for me.
In order to apply Genetic Algorithms, After the end of EACH iteration, I have modify the parameters in the Player/bot Behavior (Specifically in file PlayerInfo.Java). Something like, I may change the value for Player_HEALTH_Level=48 for the iteration 2 run, then to 56 on the third run and so on.
In oreder to do this, I need to acheive the follwing in my Testing Project inside my FOR Loop.
Perhaps may be like this
*For int i=1 to 500 do ;
String playerJAR_Path = "C:\\Users\\Player\\Netbeans\\GameProject-one-SNAPSHOT-jar.jar";
Run the Testing();
Modify the parameters in PlayerInfo.Java (Inside GameProject)
Change the values of 40 Variables in that class.
Build the GameProject Project so that, it creates a UPDATED JAR File
End FOR;*
I am really confused, as in how to build the first project automatically, and also how to change the values of the class variables.
Can any one please help me on giving some suggestions on how to achieve the same. I don't mind in what way to do this. Just be able to AUTOMATE This whole testing Process.
Other details:
1. System - Windows 7, Intel Xeon 12 Core Processor, 24GB RAM, 3 TB Flash Drive.
2. For each iteration on the For-Loop, it produces a million record (As in the console window of the Eclipse will contain a Million lines for each iteration in for loop). I also need to know, how to write this to a file, instead of flooding console.
When I tested this initially, Eclipse hang up with Out of Heap Memory Error. Then I have increased all RAM values to 2GB in the eclipse INI file. This somehow managed not to crash my eclipse with memory errors.
EDIT - Adding code to Question.
public class PlayerInfo {
public int minDistanceToFollowEnemy = 200; // This is in UT Units. If Bot sees an enemy over this distance
// He/she tries to follow him and attack.
public int probabilityToFollowEnemy = 50; // Distance between the bot and Enemy will be calculated in real time.
//If the distance is lower, chasing priority is Higher.
public int probabilityOfFlagHolderReturn = 50; // If the Bot holds the Enemy flag, what's the probability that he/she
//Runs to home base directly without being distracted to collect items, fight with enemies?
public int probabilityOfGettingEnemyFlag = 10; // If bot does not carries the enemy flag, it's probability to hunt for enemy flag.
public double maxDistanceToGetHealthPack = 1000 ; // If Bot finds a health pack within this distance && It needs a Health pack
// Then It searches one and grabs it.
public int minHealthLevel = 30; // Min Health level before bot starts looking for Health Pack
public int probabilityToGetHealthPack=80; // Probability that Bot will Pick one health pack if it sees on its path/view.
public int probabilityToSelectItem = 8 ; //Based on the current Bot's view, what's the probability that it will select to choose the item.
}
Main Class PlayerBot.java IN GameProject
public static void main(String args[]) throws PogamutException {
AddNativeBot addbot = new AddNativeBot();
//addbot.addNativeBots(4);
// starts 2 or 4 CTFBots at once
// note that this is the most easy way to get a bunch of bots running at the same time
new UT2004BotRunner<UT2004Bot, UT2004BotParameters>(CTFBot.class, "PlayerInfo").setMain(true)
.startAgents(
new CTFBotParams().setBotSkin("HumanMaleA.MercMaleC").setBotType(0).setSkillLevel(5).setTeam(0).setAgentId(new AgentId("Attacker 1"))
//,new CTFBotParams().setBotSkin("HumanFemaleA.MercFemaleA").setSkillLevel(5).setTeam(0).setAgentId(new AgentId("Attacker 2"))
//,new CTFBotParams().setBotSkin("HumanMaleA.MercMaleA") .setSkillLevel(5).setTeam(0).setAgentId(new AgentId("Attacker 3"))
//,new CTFBotParams().setBotSkin("HumanFemaleA.MercFemaleB").setSkillLevel(5).setTeam(0).setAgentId(new AgentId("Attacker 4"))
//,new CTFBotParams().setBotSkin("HumanFemaleA.MercFemaleB").setSkillLevel(5).setTeam(1).setAgentId(new AgentId("Attacker 5"))
//,new CTFBotParams().setBotSkin("HumanFemaleA.MercFemaleB").setSkillLevel(5).setTeam(1).setAgentId(new AgentId("Attacker 6"))
);
}
//Project 2
public static String[] getArgs_CTF_2v2v1() {
return new String[] {
"-y", // MATCH TYPE
"CTF", // CAPTURE THE FALG
// GENERIC CONFIG
"-u",
"C:\\UT",
"-h", // human-like-log
"-r",
"./results",
"-n",
"Test-CTF-2v2v1", // MATCH NAME
"-s",
"CTFServer",
// CUSTOM BOTS CONFIG
"-a",
"C:\\Users\\Project\\Downloads\\CTFbot\\target\\mavenproject1-1.0-SNAPSHOT.one-jar.jar;C:\\Users\\Project\\Downloads\\CTFbot\\target\\mavenproject1-1.0-SNAPSHOT.one-jar.jar",
"-b",
"CTFBot1;CTFBot2",
"-l",
"1;2",
"-k",
"HumanFemaleA.NightFemaleA;HumanFemaleA.NightFemaleA",
"-i",
"0;1",
// NATIVE BOTS CONFIG
"-c", // NATIVE BOT COUNT
"2",
"-d", // NATIVE BOT NAME
"Native1;Native2",
"-e", // NATIVE BOT SKILL
"5;6",
"-g", // NATIVE BOT TEAMS
"0;1",
// HUMANS CONFIG
"-x",
"1", // HUMAN COUNT
"-z",
"1",
// CAPTURE THE FLAG SPECIFIC CONFIG
"-m",
"CTF-LostFaith",
"-f",
"1", // SCORE LIMIT
"-t",
"5", // TIME LIMIT
};
}
//Main Class
public static void main(String[] args) throws JSAPException {
// -----------
// FOR TESTING
// -----------
//args = getArgs_DM_2v2v1();
//args = getArgs_TDM_2v2v1();
args = getArgs_CTF_2v2v1();
// --------------
// IMPLEMENTATION
// --------------
initJSAP();
header();
readConfig(args);
sanityChecks();
switch (matchType) {
case DM:
executeDeathMatch();
break;
case TDM:
executeTeamDeathMatch();
break;
case CTF:
executeCaptureTheFlag();
break;
case DD:
executeDoubleDomination();
break;
default:
fail("Unsupported match type specified " + matchTypeName + " recognized as " + matchType.shortName + "[" + matchType.name + "].");
}
}
}

Holy wall of text.
Ok, couple of things. Just because Maven created a jar for you, doesn't mean you have to use the jar. You could call the class directly.
So your testing would instantiate the class, instead of trying to run the class from the command line.
Second. You don't have to modify the internal state of the variables directly. My advice is for you to save the changes to a file and have your Player read the file. For the next iteration you modify the file and run the Player again.
Let me know if you have specific questions and I'll improve the answer.

Related

Looping a .next() in a while() loop gives NoSuchElementException in one compiler but not on another

I am a novice at coding but cannot understand why it runs fine on my machine, but when I upload my code I get a "NoSuchElementException" on line 19, "String command = keyboar.next();" I understand it has to do something with closing the scanner but I cannot figure out any other way to work it so it loops the print screen and input. Especially since it works fine when I run it on my machine.
Any insight is much appreciated here
import java.util.Scanner;
public class example1
{
public static void main(String[] args)
{
System.out.println("Enter an ending value");
Scanner keyboard = new Scanner(System.in);
int input;
input = keyboard.nextInt();
while(true){
System.out.println("Count up or down?");
String command = keyboard.next();
if (command.equalsIgnoreCase("up")) {
int one = 1;
int ten = 11;
int hund = 101;
while (one <= input) {
System.out.printf("%5d %4d %4d\n", one, ten, hund);
one++;
ten++;
hund++;
}
}
if (command.equalsIgnoreCase("down")) {
int neg = -input;
int one = -1;
int ten = 9;
int hund = 99;
while (one >= neg) {
System.out.printf("%5d %4d %4d\n", one, ten, hund);
one--;
ten--;
hund--;
}
}
}
}
}
You've created a scanner that reads from System.in. You don't close it anywhere, so I'm not sure why you wrote in your question that you feel it has something to do with that.
System.in does not represent the keyboard. It represents the java process's 'standard in' stream. If you just run java -jar foo.jar or whatnot on the command line (which is its own process, called the 'shell' - it'll be cmd.exe on windows, perhaps /bin/bash on linux. It's just an application, nothing special) - then that shell will decide that you intended to hook up the keyboard (technically, the 'terminal', which is usually virtualized, for example if you use ssh or other tools to remote your way onto another server, usually a physical keyboard isn't even connected to those things!).
But that's just because you started that process in a command line without explicitly specifying. If you double-click a jar on linux you probably won't get any terminal and nothing will be hooked up to standard in. If instead you start java -jar yourapp.jar <somefile.txt then bash will open the somefile.txt and set that up as the standard in.
The keyboard never runs out - you won't get a NoSuchElementException there.
But files run out. Given that you get this error when you 'upload' your application, clearly, something has been hooked up when whatever you uploaded it to runs your application that isn't the keyboard. It's probably a file, or at any rate, a limited stream.
You're asking for more tokens when there is nothing left to give.
Here's one obvious explanation:
This is homework or some coding exercise / coding competition.
You are uploading it to a grading server or competition testing server.
That server is (obviously - or you'd have to hire folks to type input data in over and over!) running your java app with the test data hooked up to System.in, and not an actual keyboard or even a virtualized one. Nobody is entering any keys to toss the test data at your app.
You have misunderstood the format of what the input is, so your application attempts to read more tokens than there actually are.
You can trivially reproduce this error yourself. First make a text file named 'test.txt', containing the string Hello and nothing more:
> cat test.txt
Hello
> cat Test.java
public class Test {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println(in.next());
System.out.println(in.next());
}
}
> javac Test.java
> java Test <test.txt
NoSuchElementException
After all, this code tries to read 2 tokens from the standard input, which is that test file, which doesn't have 2 tokens. The same thing is happening in your setup.
SOLUTION: Reread the exercise description, you've misunderstood the inputs. For example, I bet the description says that a blank line means you need to exit the app, or if a command quit or exit comes in, or whatnot. Your app runs forever, it's highly unlikely homework / a coding exercise requires this.

Optimize Random Forest parameters in weka?

I am trying to optimize random forest parameters using weka, the java class is as the following:
package pkg10foldcrossvalidation;
import weka.core.*;
import weka.classifiers.meta.*;
import weka.classifiers.trees.RandomForest;
import java.io.*;
public class RF_Optimizer {
public static void main(String[] args) throws Exception {
// load data
BufferedReader reader = new BufferedReader(new FileReader("C:\\Prediction Results on the testing set\\Dataset.arff"));
Instances data = new Instances(reader);
reader.close();
data.setClassIndex(data.numAttributes() - 1);
// setup classifier
CVParameterSelection ps = new CVParameterSelection();
ps.setClassifier(new RandomForest());
ps.setNumFolds(10); // using 10-fold CV
ps.addCVParameter("C 0.1 0.5 5");
// build and output best options
ps.buildClassifier(data);
System.out.println(Utils.joinOptions(ps.getBestClassifierOptions()));
}
}
But I am facing difficulty of understanding which parameters should replace the "C" and how the range of each one could be determined? And is it workable to use .addCVParameter several times for several parameters at the same time?
I tried to search for some youtube or website tutorials that explain how to change random forest parameters in java but nothing found.
Thank you
I think what you are describing, -C are the Cross-Validation parameters, not the RandomForest parameters.
Can't you just use the Explorer GUI, open a sample dataset such as glass.arff, and then right-click on the bold RandomForest string at the top of the window, then from the context menu choose "copy configuration to clipboard", and then paste that string into your java code?
After doing this right now, I've copied this string to the clipboard:
weka.classifiers.trees.RandomForest -P 100 -I 100 -num-slots 1 -K 0 -M 1.0 -V 0.001 -S 1
These are the default parameters for Weka's RandomForest learner. What these parameters mean, and which of them is most suitable for optimization, and which range of values to use for optimization I really can't tell. Most likely a very important parameter is numIterations, the -I parameter. Maybe vary it from 100, 200,... to 1000 and plot numIterations vs Accuracy, and check if the curve has smoothed out already.

Calling multiple instances of python scripts in matlab using java.lang.Runtime.getRuntime not working

I am running Matlab2017 on windows 10.
I call a python script that runs some Speech Recognition task on cloud with something like this:
userAuthCode=1;% authentication code for user account to be run on cloud
cmd = ['C:\Python27\python.exe runASR.py userAuthCode];
system(cmd);
When the above command is called, the python script runs the input audio file on the ASR cloud engine, and as it runs, I can see Speech Recognition scores for the audio file from Python in the Matlab console.
I want to do the following:
(1) Execute multiple such commands in parallel. Lets say, I have 2 input audio files (each having different audio segments), and I would like to run the above command 2 times, but in parallel, using separate processes. I was able to create a code snippet that should be able to do this:
for i=1: 2
userAuthCode=i;
cmd = ['C:\Python27\python.exe runASR.py userAuthCode];
runtime = java.lang.Runtime.getRuntime();
pid(i) = runtime.exec(cmd);
end
for i=1:2
pid(i).waitFor();
% get exit status
rc(i) = pid(i).exitValue();
end
Now, when the above code is executed, I can see ASRE scores for data1 ,but not for data 2.
The exit status in variable rc, is 0,1, which confirms this.
The problem is I do not know the cause of the error, as nothing is printed in
Matlab. How can I get error message from Python captured in a java/Matlab
variable so that i could take a look?
The issue could be that multiple Calls to
ASRE in parallel (with different user accounts of course) may not
be supported but I won't know unless I can see the error.
(2) When I run a single command standalone, as mentioned at the start of the post, I am able to see Score messages for each audio segment being printed in the Matlab console, as they are obtained from Python. However, with multi-processing using java.lang.Runtime.getRuntime() and the associated code, no messages appears in the Matlab console. Is there a way to display those messages (I am assuming display might be asynchronous?)
Thanks
sedy
One approach is to use multiprocessing in Python. The results and any error messages can be returned in a list.
Example:
Assuming you have three audio files, your_function will run 3 times in parallel with error messages returned.
import subprocess
from multiprocessing import Pool, cpu_count
def multi_processor(function_name):
# Use a regex to make a list of full paths for audio files in /some/directory
# You could also just pass in a list of audio files as a parameter to this function
file_list = []
file_list = str(subprocess.check_output("find ./some/directory -type f -iname \"*a_string_in_your_aud_file_name*\" ",shell=True)).split('\\n')
file_list = sorted(file_list)
# Test, comment out two lines above and put 3 strings in the list so your_function should run three times with 3 processors in parallel
file_list.append("test1")
file_list.append("test2")
file_list.append("test3")
# Use max number of system processors - 1
pool = Pool(processes=cpu_count()-1)
pool.daemon = True
results = {}
# for every audio file in the file list, start a new process
for aud_file in file_list:
results[aud_file] = pool.apply_async(your_function, args=("arg1", "arg2"))
# Wait for all processes to finish before proceeding
pool.close()
pool.join()
# Results and any errors are returned
return {your_function: result.get() for your_function, result in results.items()}
def your_function(arg1, arg2):
try:
print("put your stuff in this function")
your_results = ""
return your_results
except Exception as e:
return str(e)
if __name__ == "__main__":
multi_processor("your_function")

A inconsistent behaviour of JNotify on different Windows version

Our products currently using JDK 1.6, so we have to rely on JNotify for file system changes.
However during the test I noticed something that worked perfect in my Win 7 development environment stop working in XP and win server 2003. So I move on to wrote a small test program. Here is what it roughly looks like.
In the main class I only have this:
public static void main(String[] args) {
SyncUtil instance = new SyncUtil();
instance.start();
Scanner s = new Scanner(System.in);
s.nextLine();
}
SyncUtil is a class that extends Threads:
public void run() {
String path = "D:\\testFolder";
int mask = JNotify.FILE_CREATED | JNotify.FILE_DELETED | JNotify.FILE_MODIFIED | JNotify.FILE_RENAMED;
boolean watchSubtree = true;
File file = null;
try {
JNotify.addWatch(path, mask, watchSubtree, new Listener());
} catch (Exception e) {
e.printStackTrace();
}
}
The Listener class don't have any work inside, It just print log.
Now, If I run the above sample on Windows 7 / 8. It will work just fine.
But when I test it on my Win Server 2003, JNotify just stop working and Listener will not print any log at all.
What's more interesting though is if I try to make SyncUtil wait a minute when after its work. If I add:
Thread.sleep(60000);
to the end of the run function to make it wait for 60 seconds.
And instead of monitoring 1 folder, this time I'll monitor 2, I'll call them folder A and B.
What happens on the Win Server 2003 machine in this case is that if I add a file to folder A within the 60s waiting time, JNotify will properly react to the event and print a log. And it will even keep on working even if 60s has passed and the SyncUtil Thread is terminated. But now I add a file to folder B (after the 60s waiting time that is), nothing will be printed.
To sum it up, the symptom is:
1. On win 7 and win 8, JNotify will keep on working disregard of whether or not the thread calls for JNotify.addWatch() is still alive.
2. On win XP and win server 2003, JNotify can properly generate event when The Thread calls JNotify.addWatch() is running. Paths that generated at least one event when that Thread is still alive will continue to be monitored after that thread is terminated. But those paths that didn't generate any event when said thread is alive, will not work after that thread is terminated.
Now knowing this pattern I'm currently using a CountDownLatch to fix the issue, but I'm just really curious why this is happening.
I feel this kind of don't make any sense, where do you think the problem is?
I'm leaning towards the conclusion that maybe windows trigger file system event differently? Do you think this might be the case?
this is very weird, but:
adding a watch is a really quick operation, why are you adding them in a thread?

Issues plotting multiple graphs using Java, R and JavaGD?

I have successfully drawn a single graph using Java, JavaGD and R. I followed this tutorial .
Now, I have an R-script, which reads a CSV file, does some calculations. At the end, it plots 8 different graphs. When I run this script using Java/JavaGD, only 1st and 8th plot are visible. 2nd through 7th are on "inactive" windows, which are blank. I am using the exact same code as in the above mentioned link/tutorial. So I guess something is getting overwritten.
How can I draw them on proper windows? Also, the first window, if re-sized, becomes blank. How to solve this issue?
Please don't hesitate to ask for clarification, if needed. I am not sure how well I have explained the problem.
Any help/reading material is greatly appreciated.
Update 1:
Currently, I am using this code:
public static void main(String[] args) {
// TODO Auto-generated method stub
Rengine re;
String[] dummyArgs = new String[1];
dummyArgs[0] = "--vanilla";
re = new Rengine(dummyArgs, false, null);
re.eval("library(JavaGD)");
// This is the critical line: Here, we tell R that the JavaGD() device that
// it is supposed to draw to is implemented in the class MyJavaGD. If it were
// in a package (say, my.package), this should be set to
// my/package/MyJavaGD1.
re.eval("Sys.putenv('JAVAGD_CLASS_NAME'='test/MyJavaGD1')");
re.eval("JavaGD()");
// re.eval("plot(c(1,5,3,8,5), type='l', col=2)");
// re.eval("source(\"C:\\Documents and Settings\\username\\My Documents\\Test Data\\BoxPlot.r\");");
re.eval("source(\"C:\\\\Documents and Settings\\\\username\\\\My Documents\\\\sampleRScript.R\")");
re.end();
System.out.println("Done!");
}
Part of the script:
par(las=2,mfrow=c(2,1))
PlotData <- subset (m4, select=c(LotNo,def,cavity,Lift), subset=(cavity=="1"))
boxplot(Lift ~ def, data=PlotData, main="Number 1")
hist(PlotData$Lift,50, main="", xlab="Lift", ylab="Frequency")
win.graph()
par(las=2,mfrow=c(2,1))
PlotData <- subset (m4, select=c(LotNo,def,cavity,Lift), subset=(cavity=="2"))
boxplot(Lift ~ def, data=PlotData, main="Number 2")
hist(PlotData$Lift,50, main="", xlab="Lift", ylab="Frequency")
win.graph()
par(las=2,mfrow=c(2,1))
PlotData <- subset (m4, select=c(LotNo,def,cavity,Lift), subset=(cavity=="3"))
boxplot(Lift ~ def, data=PlotData, main="Number 3")
hist(PlotData$Lift,50, main="", xlab="Lift", ylab="Frequency")
.
.
.
You'll need to tell the R instance about your initialized JRI using .jengine(), otherwise it can't issue callbacks , e.g. to resize the window. As for blanked windows you'll need to provide the code that you use.
(You may want to use stats-rosuda-devel to discuss rJava/JRI/JavaGD-related issues there.)

Categories