package jaci.openrio.toast.core;
import edu.wpi.first.wpilibj.RobotBase;
import jaci.openrio.toast.core.io.usb.USBMassStorage;
import jaci.openrio.toast.core.loader.ClassPatcher;
import jaci.openrio.toast.core.loader.RobotLoader;
import jaci.openrio.toast.core.loader.simulation.DriverStationCommunications;
import jaci.openrio.toast.core.loader.simulation.SimulationGUI;
import jaci.openrio.toast.core.network.ToastSessionJoiner;
import jaci.openrio.toast.core.script.js.JavaScript;
import jaci.openrio.toast.core.security.ToastSecurityManager;
import jaci.openrio.toast.core.shared.GlobalBlackboard;
import jaci.openrio.toast.core.thread.Async;
import jaci.openrio.toast.lib.Assets;
import jaci.openrio.toast.lib.Version;
import jaci.openrio.toast.lib.crash.CrashHandler;
import jaci.openrio.toast.lib.log.Logger;
import jaci.openrio.toast.lib.log.SysLogProxy;
import jaci.openrio.toast.lib.module.ModuleConfig;
import jaci.openrio.toast.lib.profiler.Profiler;
import jaci.openrio.toast.lib.profiler.ProfilerSection;
import jaci.openrio.toast.lib.state.LoadPhase;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
/**
* The Bootstrap class for launching Toast before WPILib. This makes simulation, class patching, crash handling
* and file logging possible. WPILib's main class is called after this class has finished it's configuration
*
* @author Jaci
*/
public class ToastBootstrap {
/**
* Get the Logger for Toast
*/
public static Logger toastLogger;
public static boolean color;
/**
* Is this a simulation? This is set to true if the Launch Args include
* -sim or -simulation
*/
public static boolean isSimulation;
/**
* Is this a verification? Verifications are headless routines to 'test' the
* build process.
*/
public static boolean isVerification;
public static boolean isHeadless;
public static boolean compareStub;
/**
* Get the root folder for Toast. This is where logs, modules,
* and just about everything for toast is saved.
*/
public static File toastHome = new File("/home/lvuser/toast/");
public static File robotHome = new File("/home/lvuser/");
public static long startTimeNS;
public static long startTimeMS;
public static long endTimeMS;
/**
* The Main Method. Called when the Toast Program is started. This contains multiple arguments, such as
* -sim, -verify, -groovy, -groovyClass, -core and any others that are required. More of these are outlined in
* the Whitepaper and various Loaders. Modules may also add their own arguments by retrieving 'runtime_args' from
* the GlobalBlackboard
*/
public static void main(String[] args) {
startTimeNS = System.nanoTime();
startTimeMS = System.currentTimeMillis();
color = true;
ProfilerSection profiler = Profiler.INSTANCE.section("Setup");
JavaScript.startLoading();
profiler.start("ParseArgs");
for (int i = 0; i < args.length; i++) {
String arg = args[i];
String nextArg = null;
try {
nextArg = args[i+1];
} catch (Exception e) {}
if (arg.equalsIgnoreCase("-simulation") || arg.equals("-sim")) {
isSimulation = true;
try {
if (!nextArg.equals(".")) {
if (nextArg.equalsIgnoreCase("--search")) {
RobotLoader.search = true;
} else {
RobotLoader.manualLoadedClasses.add(nextArg);
}
}
} catch (Exception e) { }
} else if (arg.equalsIgnoreCase("-verify") || arg.equalsIgnoreCase("-vf")) {
isSimulation = true;
isVerification = true;
} else if (arg.equalsIgnoreCase("-core")) {
try {
if (!nextArg.equals(".")) {
RobotLoader.coreClasses.add(nextArg);
RobotLoader.manualLoadedClasses.add(nextArg);
}
} catch (Exception e) { }
} else if (arg.equalsIgnoreCase("--no-color")) {
color = false;
} else if (arg.equalsIgnoreCase("--join")) {
ToastSessionJoiner.init();
return;
} else if (arg.equalsIgnoreCase("--headless")) {
isHeadless = true;
} else if (arg.equalsIgnoreCase("--stub")) {
compareStub = true;
}
}
profiler.stop("ParseArgs");
if (compareStub) {
System.out.println("Immediately exiting -- we've been told to exit before initialization for memory and utilization measurement purposes. Type something to end the program.");
try {
System.in.read();
} catch (IOException e) {
return;
}
return;
}
if (isSimulation) {
toastHome = new File("toast/").getAbsoluteFile();
robotHome = new File("./").getAbsoluteFile();
}
toastHome.mkdirs();
LoadPhase.BOOTSTRAP.transition();
profiler.start("Logger");
SysLogProxy.init();
profiler.stop("Logger");
profiler.start("Crash");
CrashHandler.init();
profiler.stop("Crash");
profiler.start("Misc");
System.out.println(Assets.getAscii("splash"));
toastLogger = new Logger("Toast", Logger.ATTR_DEFAULT);
new GlobalBlackboard();
GlobalBlackboard.INSTANCE.put("runtime_args", args);
profiler.stop("Misc");
profiler.start("Version");
Version.init();
profiler.stop("Version");
// -------- NEW PHASE -------- //
LoadPhase.CORE_PREINIT.transition();
RobotLoader.preinit(Profiler.INSTANCE.section("RobotLoader"));
// -------- NEW PHASE -------- //
LoadPhase.CORE_INIT.transition();
RobotLoader.initCore(Profiler.INSTANCE.section("RobotLoader"));
if (args.length > 0)
toastLogger.info("Toast Started with Run Arguments: " + Arrays.toString(args));
ModuleConfig.init();
// -------- NEW PHASE -------- //
LoadPhase.PRE_INIT.transition();
toastLogger.info("Slicing Loaf...");
USBMassStorage.init();
profiler.start("Configuration");
ToastConfiguration.init();
profiler.stop("Configuration");
profiler.start("ThreadPool");
Async.init();
profiler.stop("ThreadPool");
ClassPatcher classLoader = new ClassPatcher();
classLoader.identifyPatches(isSimulation);
if (isSimulation && !isVerification && !isHeadless) {
SimulationGUI.main(args);
DriverStationCommunications.init();
}
// -------- NEW PHASE -------- //
LoadPhase.INIT.transition();
toastLogger.info("Nuking Toast...");
RobotLoader.postCore(Profiler.INSTANCE.section("RobotLoader"));
profiler.start("Security");
ToastSecurityManager.init();
profiler.stop("Security");
profiler.start("WPILib");
RobotBase.main(args);
}
}