diff --git a/TeamCode/src/main/java/org/cyberarm/engine/V2/CyberarmEngine.java b/TeamCode/src/main/java/org/cyberarm/engine/V2/CyberarmEngine.java index 6dbc79e..2a8307e 100644 --- a/TeamCode/src/main/java/org/cyberarm/engine/V2/CyberarmEngine.java +++ b/TeamCode/src/main/java/org/cyberarm/engine/V2/CyberarmEngine.java @@ -5,7 +5,11 @@ import android.util.Log; import com.qualcomm.robotcore.eventloop.opmode.OpMode; import com.qualcomm.robotcore.hardware.Gamepad; -import java.util.ArrayList; +import org.timecrafters.TimeCraftersConfigurationTool.library.TimeCraftersConfiguration; +import org.timecrafters.TimeCraftersConfigurationTool.library.backend.config.Action; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.concurrent.CopyOnWriteArrayList; @@ -278,4 +282,60 @@ public abstract class CyberarmEngine extends OpMode { public int getActiveStateIndex() { return activeStateIndex; } + + /** + * Automatically populates states from a TimeCraftersConfiguration Group actions + * requires action comments to start with an @ character followed by the class name + * state must have a construction that takes 3 arguments: object, groupName, and actionName + * @param configuration TimeCraftersConfiguration + * @param packageName Package name where states are defined + * @param object Object to pass to as first argument to states constructor + * @param objectClass Class to cast object to + * @param groupName Group name + */ + protected void setupFromConfig(TimeCraftersConfiguration configuration, String packageName, Object object, Class objectClass, String groupName) { + CyberarmState lastState = null; + String lastActionName = null; + String[] lastActionNameSplit = new String[0]; + + for (Action action : configuration.group(groupName).getActions()) { + if (!action.enabled) { + continue; + } + + String className = null; + + if (action.comment.startsWith("@")) { + String[] split = action.comment.split("@"); + className = split[1].split("[ \\-]")[0]; + } else { + throw(new RuntimeException("setupFromConfig: Action \"" + action.name + "\" in group \"" + groupName + "\" is missing magic @ in comment.")); + } + + Class klass = null; + try { + klass = Class.forName("" + packageName + "." + className); + if (klass != null) { + String[] actionNameSplit = action.name.split("-"); + Constructor constructor = klass.getConstructor(objectClass, String.class, String.class); + CyberarmState state = (CyberarmState) constructor.newInstance(objectClass.cast(object), groupName, action.name); + + if (lastState != null && lastActionNameSplit.length == 2 && actionNameSplit.length == 2 && actionNameSplit[0].equals(lastActionNameSplit[0])) + { + lastState.addParallelState(state); + } else { + addState(state); + lastState = state; + } + + lastActionName = action.name; + lastActionNameSplit = lastActionName.split("-"); + } + } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) { + e.printStackTrace(); + + throw(new RuntimeException(e)); + } + } + } } diff --git a/TeamCode/src/main/java/org/timecrafters/testing/engine/DynamicSetupEngine.java b/TeamCode/src/main/java/org/timecrafters/testing/engine/DynamicSetupEngine.java new file mode 100644 index 0000000..f870274 --- /dev/null +++ b/TeamCode/src/main/java/org/timecrafters/testing/engine/DynamicSetupEngine.java @@ -0,0 +1,33 @@ +package org.timecrafters.testing.engine; + +import com.qualcomm.robotcore.eventloop.opmode.Autonomous; +import com.qualcomm.robotcore.eventloop.opmode.TeleOp; + +import org.cyberarm.engine.V2.CyberarmEngine; +import org.cyberarm.engine.V2.CyberarmState; +import org.timecrafters.TimeCraftersConfigurationTool.library.TimeCraftersConfiguration; + +@TeleOp(name = "DynamicSetupEngine") +public class DynamicSetupEngine extends CyberarmEngine { + public class Robot { + public TimeCraftersConfiguration configuration; + + public Robot() { + configuration = new TimeCraftersConfiguration(); + } + } + + @Override + public void setup() { + this.showStateChildrenListInTelemetry = true; + Robot robot = new Robot(); + + setupFromConfig( + robot.configuration, + "org.timecrafters.testing.states", + robot, + Robot.class, + "LeftAutonomous" + ); + } +} diff --git a/TeamCode/src/main/java/org/timecrafters/testing/states/DynamicSetupState.java b/TeamCode/src/main/java/org/timecrafters/testing/states/DynamicSetupState.java new file mode 100644 index 0000000..cd2bc39 --- /dev/null +++ b/TeamCode/src/main/java/org/timecrafters/testing/states/DynamicSetupState.java @@ -0,0 +1,26 @@ +package org.timecrafters.testing.states; + +import org.cyberarm.engine.V2.CyberarmState; +import org.timecrafters.testing.engine.DynamicSetupEngine; + +public class DynamicSetupState extends CyberarmState { + private long delay; + + public DynamicSetupState(DynamicSetupEngine.Robot robot, String groupName, String actionName) { + delay = robot.configuration.variable(groupName, actionName, "delay").value(); + } + + @Override + public void exec() { + if (runTime() >= delay) { + setHasFinished(true); + } + } + + @Override + public void telemetry() { + engine.telemetry.addData("runTime", runTime()); + engine.telemetry.addData("delay", delay); + engine.telemetry.addLine(progressBar(20, (runTime() / delay) * 100)); + } +}