This is in roboleague.gui.RoboLeagueGui. Starting from the end of the constructor:
// new Thread() { // public void run() { bg_initialize(); // } // }.start(); run(args); } private void run(String[] args) { if (args.length == 0) { return; } int i = 0; String file = args[i++]; if (!file.endsWith(".xml")) { System.out.println(file + " should end with .xml"); return; } if (args.length == 1) { if (load(new File(file))) { runSeasons(1); } return; } int numSeasons = Integer.parseInt(args[i++]); List<Variable> vars = new LinkedList<Variable>(); while (i < args.length) { i = makeVariableList(args, vars, i); } System.out.println("RUNNING SINGLE VARIABLES"); for (int season = 1; season <= numSeasons; ++season) { int minRun = Integer.MAX_VALUE; for (i = 0; i < vars.size(); ++i) { int finished = runSingle(vars, i, file, season); vars.get(i).initialize(); if (finished == -1) { System.out.println("INTURRUPTED!"); return; } if (finished < minRun) { minRun = finished; } } season = minRun; System.out.println("FINISHED SEASON " + season); } System.out.println("RUNNING COMBINED VARIABLES"); for (int season = 1; season <= numSeasons; ++season) { season = runCombined(vars, 0, file, season); if (season == -1) { System.out.println("INTURRUPTED!"); return; } System.out.println("FINISHED SEASON " + season); } System.out.println("DONE!"); gracefullExit(); } private int runSingle(List<Variable> vars, int i, String originalFile, int season) { Variable var = vars.get(i); int minCount = Integer.MAX_VALUE; for (String val : var.values) { System.setProperty(var.name, val); int count = run(vars, originalFile, season); if (count == -1) { return -1; } if (count < minCount) { minCount = count; } } return minCount; } // returns min seasons run, or -1 when there was an inturrupt private int runCombined(List<Variable> vars, int i, String originalFile, int curSeason) { if (i == vars.size()) { return run(vars, originalFile, curSeason); } Variable var = vars.get(i); int minCount = Integer.MAX_VALUE; for (String val : var.values) { System.setProperty(var.name, val.toString()); int count = runCombined(vars, i + 1, originalFile, curSeason); if (count == -1) { return -1; } if (count < minCount) { minCount = count; } } return minCount; } private int run(List<Variable> vars, String originalFile, int curSeason) { File file = new File(getFilename(vars, originalFile)); if (exists(file, originalFile) && load(file)) { int seasonCount = getCompletedSeasonCount(); if (seasonCount < curSeason) { runSeasons(1); try { runSeasonJob.join(); } catch (InterruptedException e) { // no prob, we'll abort when inturrupted // possible race condition if inturrupted right away, // but the job is still running, we get the old season // count, then the new non-terminated state (it depends // on the order in which the state & season count are // updated) } int newSeasonCount = getCompletedSeasonCount(); if (newSeasonCount == seasonCount) { return -1; } return newSeasonCount; } System.out.println(file + " already ran season " + curSeason); return seasonCount; } System.out.println("Couldn't find, create, or run " + file); return Integer.MAX_VALUE; } private String getFilename(List<Variable> vars, String originalFile) { String filename = originalFile.substring(0, originalFile.length() - 4); Set<Variable> varSet = new TreeSet<Variable>(vars); for (Variable var : varSet) { filename += "-" + var; } return filename + ".xml"; } private boolean load(File file) { CompetitionDataModel before = loadedDataModel; bg_openDataModel(file); if (loadedDataModel == null || loadedDataModel == before) { System.out.println("Load failed"); return false; } return true; } public int getCompletedSeasonCount() { int num = 0; if (loadedDataModel instanceof Division) { Division division = (Division) loadedDataModel; num = division.getSeasonCount(); } else if (loadedDataModel instanceof League) { League league = (League) loadedDataModel; num = league.getSeasonCount(); } else { // loadedDataModel is null, maybe? return 0; } if (!loadedDataModel.getTerminated()) { --num; } return num; } private boolean exists(File file, String originalFile) { if (file.isFile()) { return true; } // nope ... try to make it! try { InputStream in = new FileInputStream(originalFile); OutputStream out = new FileOutputStream(file); for (int b = in.read(); b != -1; b = in.read()) { out.write(b); } in.close(); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } return true; } // <property> <numvals> <value> <value> <value> ... // <property> number <start> <end> <step> private int makeVariableList(String[] args, List<Variable> vars, int i) { String property = args[i++]; List<String> vals = new LinkedList<String>(); String type = args[i++]; if ("number".equals(type)) { double start = Double.parseDouble(args[i++]); double end = Double.parseDouble(args[i++]); double step = Double.parseDouble(args[i++]); for (double val = start; val <= end; val += step) { vals.add(Double.toString(val)); } } else { for (int j = Integer.parseInt(type); j > 0; --j) { vals.add(args[i++]); } } vars.add(new Variable(property, vals)); return i; } class Variable implements Comparable<Variable> { final String name; final List<String> values; Variable(String name, List<String> values) { this.name = name; this.values = values; initialize(); } public void initialize() { System.setProperty(name, values.get(0)); } public String toString() { return name + "=" + System.getProperty(name); } public int compareTo(Variable o) { return name.compareTo(o.name); } }
Now, to use the new mod, pass command line aruments to roboleague in this form:
java roboleague.gui.RoboLeagueGui? {base-xml-file} {target-number-of-seasons} {variable}*
Where a variable is in the form:
{variable-name} {number-of-values} {value} {value} {value} ...or
{variable-name} number {start-value} {end-value} {step-size}
This will set the appropriate values for each variable in System.properties, as many of them as you want, and run them in every combination. The results for each combination of variables will be stored in a file starting with the name of the base xml file, followed by the names of the variables and their values for the runs in that file. So, test.xml becomes test_var1-value1.xml and test_var1-value2.xml. Note that test.xml itself should not contain any results, or else they will be carried over into every run.
The code is well behaved if you inturrupt it, and it knows how to start back up again where it left off the next time you run Roboleague with the same command line args.
To make use of these variables in System.properties (where the new mod puts them), do something like this:
int variable = default-value; String cmdVariable = System.getProperty("variable-name-in-command-line"); if (cmdVariable != null) { try { variable = (int) Double.parseDouble(cmdVariable); } catch (NumberFormatException err) { System.out.println("Couldn't understand " + cmdVariable); } } System.out.println("Using pattern depth " + variable);
Notice that all "number" variables on the command line get stored in System.properties using Double.toString(value), so they should be de-coded with Double.parseDouble(valueString), not, for example, Integer.parseInt(...).