Skip to content

Commit 45c9029

Browse files
author
BuildTools
committed
refactor ChoiceMenu
1 parent 1a0721f commit 45c9029

3 files changed

Lines changed: 91 additions & 46 deletions

File tree

Marrow/src/main/java/com/skeletonarmy/marrow/MarrowGamepad.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public MarrowGamepad(OpMode opMode, Gamepad gamepad) {
111111
* Updates the internal gamepad state.
112112
*/
113113
public void update() {
114-
if (opMode.time == lastOpModeTime) return; // Skip update if it was already called this frame
114+
if (opMode.time == lastOpModeTime) return; // Skip update if it was already called this frame. This is so it runs only once per loop.
115115

116116
// Save snapshot (last frame) into previous
117117
previous.copy(snapshot);

Marrow/src/main/java/com/skeletonarmy/marrow/autonomous/AutoOpMode.java

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,15 @@ private static class StateEntry {
4646

4747
private String currentState = null;
4848

49-
private ChoiceMenu choiceMenu;
50-
5149
private Supplier<Boolean> fallbackCondition = () -> false;
5250
private Runnable fallbackFunction = () -> {};
5351
private boolean didFallback = false;
5452

5553
private double autonomousDuration = 30;
5654

57-
protected ElapsedTime runtime = new ElapsedTime();
55+
public ElapsedTime runtime = new ElapsedTime();
56+
57+
public ChoiceMenu choiceMenu;
5858

5959
public MarrowGamepad gamepad1;
6060
public MarrowGamepad gamepad2;
@@ -108,7 +108,7 @@ private void internalEarlyInit() {
108108
}
109109

110110
private void internalLateInit() {
111-
new Thread(this::preAutonomousSetup).start();
111+
preAutonomousSetup();
112112
}
113113

114114
private void internalInitLoop(){
@@ -345,16 +345,6 @@ protected void setFallbackState(Supplier<Boolean> condition, Runnable handler) {
345345
fallbackFunction = handler;
346346
}
347347

348-
/**
349-
* Prompts the user with a specified {@link Prompt} and waits for a selection.
350-
*
351-
* @param prompt The {@link Prompt} to present to the user
352-
* @return The selected result of type {@code T}
353-
*/
354-
protected <T> T prompt(Prompt<T> prompt) {
355-
return choiceMenu.prompt(prompt);
356-
}
357-
358348
/**
359349
* Sets the duration of the autonomous period, typically used for debugging purposes.
360350
* This value is used in {@link #isEnoughTime()}.

Marrow/src/main/java/com/skeletonarmy/marrow/autonomous/ChoiceMenu.java

Lines changed: 86 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,32 @@
88
import com.skeletonarmy.marrow.prompts.Prompt;
99

1010
import java.util.ArrayList;
11+
import java.util.HashMap;
1112
import java.util.List;
13+
import java.util.Map;
14+
import java.util.function.Supplier;
1215

1316
public class ChoiceMenu {
17+
private final OpMode opMode;
1418
private final Telemetry telemetry;
1519
private final MarrowGamepad gamepad1;
1620
private final MarrowGamepad gamepad2;
1721

18-
private final List<PromptResult<?>> promptResults = new ArrayList<>();
22+
private final List<KeyPromptPair<?>> prompts = new ArrayList<>();
23+
private final Map<String, Object> results = new HashMap<>();
24+
1925
private int currentIndex = 0;
26+
private double lastOpModeTime = -1;
2027

2128
public ChoiceMenu(OpMode opMode, Gamepad gamepad1, Gamepad gamepad2) {
29+
this.opMode = opMode;
2230
this.telemetry = opMode.telemetry;
2331
this.gamepad1 = new MarrowGamepad(opMode, gamepad1);
2432
this.gamepad2 = new MarrowGamepad(opMode, gamepad2);
2533
}
2634

2735
public ChoiceMenu(OpMode opMode, MarrowGamepad gamepad1, MarrowGamepad gamepad2) {
36+
this.opMode = opMode;
2837
this.telemetry = opMode.telemetry;
2938
this.gamepad1 = gamepad1;
3039
this.gamepad2 = gamepad2;
@@ -33,13 +42,44 @@ public ChoiceMenu(OpMode opMode, MarrowGamepad gamepad1, MarrowGamepad gamepad2)
3342
/**
3443
* Add a prompt to the queue.
3544
*/
36-
private <T> void enqueuePrompt(Prompt<T> prompt) {
37-
promptResults.add(new PromptResult<>(prompt));
45+
public <T> void enqueuePrompt(String key, Prompt<T> prompt) {
46+
prompts.add(new KeyPromptPair<>(key, prompt));
47+
}
48+
49+
/**
50+
* Add a prompt to the queue.
51+
*/
52+
public <T> void enqueuePrompt(String key, Supplier<Prompt<T>> promptSupplier) {
53+
prompts.add(new KeyPromptPair<>(key, promptSupplier));
54+
}
55+
56+
57+
/**
58+
* Gets the chosen value of a prompt from its key.
59+
*
60+
* @param key The prompt's key
61+
* @return The value of the prompt result
62+
*/
63+
@SuppressWarnings("unchecked")
64+
public <T> T get(String key) {
65+
return (T) results.get(key);
66+
}
67+
68+
/**
69+
* Gets the chosen value of a prompt from its key.
70+
*
71+
* @param key The prompt's key
72+
* @param defaultValue A default value if the value doesn't exist
73+
* @return The value of the prompt result
74+
*/
75+
@SuppressWarnings("unchecked")
76+
public <T> T getOrDefault(String key, T defaultValue) {
77+
return (T) results.getOrDefault(key, defaultValue);
3878
}
3979

4080
/**
4181
* Handles the prompts and inputs. Should be called in a loop.
42-
* @return True if there are no more prompts to process
82+
* @return True if there are no more prompts to process, false otherwise
4383
*/
4484
private boolean processPrompts() {
4585
// Handle back navigation
@@ -48,49 +88,64 @@ private boolean processPrompts() {
4888
}
4989

5090
// No prompts left
51-
if (currentIndex >= promptResults.size()) {
91+
if (currentIndex >= prompts.size()) {
5292
return true;
5393
}
5494

55-
PromptResult current = promptResults.get(currentIndex);
56-
Object result = current.prompt.process(gamepad1, gamepad2, telemetry);
95+
KeyPromptPair<?> current = prompts.get(currentIndex);
96+
Prompt<?> prompt = current.getPrompt();
5797

98+
// Skip if prompt is null
99+
if (prompt == null) {
100+
currentIndex++;
101+
return false;
102+
}
103+
104+
Object result = prompt.process(gamepad1, gamepad2, telemetry);
58105
if (result != null) {
59-
current.result = result;
106+
results.put(current.getKey(), result);
60107
currentIndex++;
61108
}
62109

63110
return false;
64111
}
65112

66-
/**
67-
* Prompts the user and waits for a result. This will block until the result is chosen.
68-
*/
69-
@SuppressWarnings("unchecked")
70-
public <T> T prompt(Prompt<T> prompt) {
71-
enqueuePrompt(prompt);
72-
73-
// Process the prompts until a result is selected for the current prompt
74-
while (!processPrompts()) {
75-
gamepad1.update();
76-
gamepad2.update();
77-
telemetry.update();
78-
telemetry.clearAll();
79-
}
113+
public void run() {
114+
boolean finished = false;
80115

81-
// Return the result of the prompt
82-
return (T) promptResults.get(promptResults.size() - 1).result;
116+
while (!finished) {
117+
if (opMode.time == lastOpModeTime) continue; // Skip if it was already called this frame. This is so it runs only once per loop.
118+
119+
finished = processPrompts();
120+
lastOpModeTime = opMode.time;
121+
}
83122
}
84123

85-
/**
86-
* A helper class to keep prompt and its result together.
87-
*/
88-
private static class PromptResult<T> {
89-
public final Prompt<T> prompt;
90-
public T result;
124+
private static class KeyPromptPair<T> {
125+
private final String key;
126+
private final Prompt<T> prompt;
127+
private final Supplier<Prompt<T>> promptSupplier;
91128

92-
public PromptResult(Prompt<T> prompt) {
129+
public KeyPromptPair(String key, Prompt<T> prompt) {
130+
this.key = key;
93131
this.prompt = prompt;
132+
this.promptSupplier = null;
133+
}
134+
135+
public KeyPromptPair(String key, Supplier<Prompt<T>> promptSupplier) {
136+
this.key = key;
137+
this.prompt = null;
138+
this.promptSupplier = promptSupplier;
139+
}
140+
141+
public String getKey() {
142+
return key;
143+
}
144+
145+
public Prompt<T> getPrompt() {
146+
if (prompt != null) return prompt;
147+
if (promptSupplier != null) return promptSupplier.get();
148+
return null;
94149
}
95150
}
96151
}

0 commit comments

Comments
 (0)